FolderIcon.java revision badf71e11fba2d6efa1d1bcca9542001f90a3777
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
197c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohenimport java.util.ArrayList;
207c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen
212801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.Animator;
222801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.AnimatorListenerAdapter;
232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.ValueAnimator;
242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.Resources;
27a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport android.graphics.Canvas;
28f4b08913677e18a8412930972237b91d5a946d95Adam Cohenimport android.graphics.Color;
29badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohenimport android.graphics.PorterDuff;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.drawable.Drawable;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.LayoutInflater;
337c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohenimport android.view.View;
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewGroup;
35a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport android.widget.FrameLayout;
36a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport android.widget.TextView;
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guyimport com.android.launcher.R;
39a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport com.android.launcher2.FolderInfo.FolderListener;
40edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * An icon that can appear on in the workspace representing an {@link UserFolder}.
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
44a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenpublic class FolderIcon extends FrameLayout implements DropTarget, FolderListener {
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
46a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    Folder mFolder;
47a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    FolderInfo mInfo;
48a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
49badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The number of icons to display in the
50a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    private static final int NUM_ITEMS_IN_PREVIEW = 4;
51f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    private static final int CONSUMPTION_ANIMATION_DURATION = 100;
52badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
53badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The degree to which the inner ring grows when accepting drop
54073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private static final float INNER_RING_GROWTH_FACTOR = 0.1f;
55badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
56badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The degree to which the inner ring is scaled in its natural state
57badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    private static final float INNER_RING_BASELINE_SCALE = 1.0f;
58badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
59badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The degree to which the outer ring grows when accepting drop
60073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private static final float OUTER_RING_BASELINE_SCALE = 0.7f;
61badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
62badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The degree to which the outer ring is scaled in its natural state
63073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
64badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
65badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The amount of vertical spread between items in the stack [0...1]
66badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
67badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
68badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The degree to which the item in the back of the stack is scaled [0...1]
69badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // (0 means it's not scaled at all, 1 means it's scaled to nothing)
70badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    private static final float PERSPECTIVE_SCALE_FACTOR = 0.3f;
71badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
72badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    // The percentage of the FolderIcons view that will be dedicated to the items preview
73badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    private static final float SPACE_PERCENTAGE_FOR_ICONS = 0.8f;
7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
75073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    public static Drawable sFolderOuterRingDrawable = null;
76f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    public static Drawable sFolderInnerRingDrawable = null;
77073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
78073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private int mOriginalWidth = -1;
79073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private int mOriginalHeight = -1;
80073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
81073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private int mFolderLocX;
82073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private int mFolderLocY;
83073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private float mOuterRingScale;
84f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    private float mInnerRingScale;
852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public FolderIcon(Context context, AttributeSet attrs) {
8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public FolderIcon(Context context) {
9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context);
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
957a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung        final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
967a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung        final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
977a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung        final Workspace workspace = (Workspace) cellLayout.getParent();
987a1d16555d80135e61b90158ff3c1e3f963bd8b8Winson Chung        return !workspace.isSmall();
990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
1000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
102df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            FolderInfo folderInfo, IconCache iconCache) {
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final Resources resources = launcher.getResources();
1072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        Drawable d = iconCache.getFullResIcon(resources, R.drawable.portal_ring_inner_holo);
108a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        icon.setBackgroundDrawable(d);
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        icon.setTag(folderInfo);
11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        icon.setOnClickListener(launcher);
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        icon.mInfo = folderInfo;
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        icon.mLauncher = launcher;
113a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
114a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        Folder folder = Folder.fromXml(launcher);
115a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        folder.setDragController(launcher.getDragController());
116a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        folder.setLauncher(launcher);
1172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        folder.setFolderIcon(icon);
118a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        folder.bind(folderInfo);
119a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        icon.mFolder = folder;
120a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
121a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        folderInfo.addListener(icon);
122073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        if (sFolderOuterRingDrawable == null) {
123073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen            sFolderOuterRingDrawable =
124073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                    launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
125073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        }
126a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
127f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        if (sFolderInnerRingDrawable == null) {
128f4b08913677e18a8412930972237b91d5a946d95Adam Cohen            sFolderInnerRingDrawable =
129f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                    launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
130f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        }
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return icon;
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
134073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private boolean willAcceptItem(ItemInfo item) {
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int itemType = item.itemType;
1362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
1372801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
138073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                !mFolder.isFull() && item != mInfo);
139073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
140073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
141cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public boolean acceptDrop(DragObject d) {
142cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        final ItemInfo item = (ItemInfo) d.dragInfo;
143073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        return willAcceptItem(item);
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
146df0353815c629fc678824b07a234b89a1ff94208Adam Cohen    public void addItem(ShortcutInfo item) {
147df0353815c629fc678824b07a234b89a1ff94208Adam Cohen        mInfo.add(item);
148a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
149df0353815c629fc678824b07a234b89a1ff94208Adam Cohen    }
150df0353815c629fc678824b07a234b89a1ff94208Adam Cohen
151cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public void onDrop(DragObject d) {
1520589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        ShortcutInfo item;
153cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        if (d.dragInfo instanceof ApplicationInfo) {
1540589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            // Came from all apps -- make a copy
155cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
1560589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        } else {
157cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            item = (ShortcutInfo) d.dragInfo;
1580589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        }
15966d72178af91d455700875635473be942bc90e54Michael Jurka        item.cellX = -1;
16066d72178af91d455700875635473be942bc90e54Michael Jurka        item.cellY = -1;
161df0353815c629fc678824b07a234b89a1ff94208Adam Cohen        addItem(item);
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    void saveState(CellLayout.LayoutParams lp) {
1652801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mOriginalWidth = lp.width;
1662801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mOriginalHeight = lp.height;
1672801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
1682801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
169073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private void animateToAcceptState() {
170f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
171f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.setDuration(CONSUMPTION_ANIMATION_DURATION);
172f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.addUpdateListener(new AnimatorUpdateListener() {
173073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
174073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
175073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
176f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR;
177073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                mLauncher.getWorkspace().invalidate();
178073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                invalidate();
1792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
1802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        });
181f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.addListener(new AnimatorListenerAdapter() {
1822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            @Override
1832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            public void onAnimationEnd(Animator animation) {
184f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                // Instead of setting the background drawable to null, we set the color to
185f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                // transparent. Setting the background drawable to null results in onDraw
186f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                // not getting called.
187f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                setBackgroundColor(Color.TRANSPARENT);
188f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                requestLayout();
189073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen            }
190073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        });
191f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.start();
192f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    }
193073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
194f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    private void animateToNaturalState() {
195f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
196f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.setDuration(CONSUMPTION_ANIMATION_DURATION);
197f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.addUpdateListener(new AnimatorUpdateListener() {
198073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
199073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
200073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
201073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                        - percent * OUTER_RING_GROWTH_FACTOR;
202f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR
203f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                        - percent * INNER_RING_GROWTH_FACTOR;
204073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                mLauncher.getWorkspace().invalidate();
205f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                invalidate();
2062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
2072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        });
208f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.addListener(new AnimatorListenerAdapter() {
209f4b08913677e18a8412930972237b91d5a946d95Adam Cohen            @Override
210f4b08913677e18a8412930972237b91d5a946d95Adam Cohen            public void onAnimationEnd(Animator animation) {
211f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                setBackgroundDrawable(sFolderInnerRingDrawable);
212f4b08913677e18a8412930972237b91d5a946d95Adam Cohen                mLauncher.getWorkspace().hideFolderAccept(FolderIcon.this);
213f4b08913677e18a8412930972237b91d5a946d95Adam Cohen            }
214f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        });
215f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        va.start();
21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
217440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
218073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    private void determineFolderLocationInWorkspace() {
219073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        int tvLocation[] = new int[2];
220073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        int wsLocation[] = new int[2];
221073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        getLocationOnScreen(tvLocation);
222073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        mLauncher.getWorkspace().getLocationOnScreen(wsLocation);
223073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        mFolderLocX = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2;
224073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        mFolderLocY = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
225073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
226073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
227cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public void onDragEnter(DragObject d) {
228cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
229073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        determineFolderLocationInWorkspace();
230073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        mLauncher.getWorkspace().showFolderAccept(this);
231073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        animateToAcceptState();
232073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
233073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
234cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public void onDragOver(DragObject d) {
235073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
236073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
237cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public void onDragExit(DragObject d) {
238cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
239073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        animateToNaturalState();
240073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
241073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
242cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public DropTarget getDropTargetDelegate(DragObject d) {
243440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
244440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
245a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
246073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    public void getFolderLocation(int[] loc) {
247073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        loc[0] = mFolderLocX;
248073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        loc[1] = mFolderLocY;
249073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
250073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
251073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    public float getOuterRingScale() {
252073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        return mOuterRingScale;
253073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen    }
254073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
255f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    public float getInnerRingScale() {
256f4b08913677e18a8412930972237b91d5a946d95Adam Cohen        return mInnerRingScale;
257f4b08913677e18a8412930972237b91d5a946d95Adam Cohen    }
258f4b08913677e18a8412930972237b91d5a946d95Adam Cohen
259a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    @Override
260a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    protected void onDraw(Canvas canvas) {
261a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        if (mFolder == null) return;
262a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        if (mFolder.getItemCount() == 0) return;
263a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
264a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        canvas.save();
265a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        TextView v = (TextView) mFolder.getItemAt(0);
266a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        Drawable d = v.getCompoundDrawables()[1];
267a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
268073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        if (mOriginalWidth < 0 || mOriginalHeight < 0) {
269073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen            mOriginalWidth = getMeasuredWidth();
270073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen            mOriginalHeight = getMeasuredHeight();
271073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        }
272073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen
273badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        int unscaledHeight = (int) (d.getIntrinsicHeight() * (1 + PERSPECTIVE_SHIFT_FACTOR));
274badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        float baselineIconScale = SPACE_PERCENTAGE_FOR_ICONS / (unscaledHeight / (mOriginalHeight * 1.0f));
275badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
276badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        int baselineHeight = (int) (d.getIntrinsicHeight() * baselineIconScale);
277badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        int totalStackHeight = (int) (baselineHeight * (1 + PERSPECTIVE_SHIFT_FACTOR));
278badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        int baselineWidth = (int) (d.getIntrinsicWidth() * baselineIconScale);
279badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        float maxPerpectiveShift = baselineHeight * PERSPECTIVE_SHIFT_FACTOR;
280a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
2817c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        ArrayList<View> items = mFolder.getItemsInReadingOrder();
2827c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        int firstItemIndex = Math.max(0, items.size() - NUM_ITEMS_IN_PREVIEW);
283badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
284badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        int xShift = (int) (mOriginalWidth - baselineWidth) / 2;
285badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        int yShift = (int) (mOriginalHeight - totalStackHeight) / 2;
286badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        canvas.translate(xShift, yShift);
2874dbe6d993485a702505ee4895db94aaa89655f2cAdam Cohen        for (int i = firstItemIndex; i < items.size(); i++) {
288badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            int index = i - firstItemIndex;
289badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            index += Math.max(0, NUM_ITEMS_IN_PREVIEW - items.size());
290badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
291badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1);
292badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
293badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            r = (float) Math.pow(r, 2);
294badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
295badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            float transY = r * maxPerpectiveShift;
296badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            float transX = (1 - scale) * baselineWidth / 2.0f;
297badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
2987c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            v = (TextView) items.get(i);
299a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen            d = v.getCompoundDrawables()[1];
300a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
301badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            canvas.save();
302badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            canvas.translate(transX, transY);
303badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            canvas.scale(baselineIconScale * scale, baselineIconScale * scale);
304f4b08913677e18a8412930972237b91d5a946d95Adam Cohen
305badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            int overlayAlpha = (int) (80 * (1 - r));
306a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen            if (d != null) {
307a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen                d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
308badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen                d.setColorFilter(Color.argb(overlayAlpha, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);
309a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen                d.draw(canvas);
310badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen                d.clearColorFilter();
311a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen            }
312badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            canvas.restore();
313a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        }
314a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
315a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        canvas.restore();
316a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    }
317a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
318a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    public void onAdd(ShortcutInfo item) {
319a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        invalidate();
320a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        requestLayout();
321a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    }
322a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
323a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    public void onRemove(ShortcutInfo item) {
324a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        invalidate();
325a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        requestLayout();
326a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    }
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
328