2009-03-03 19:32:27 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2008 The Android Open Source Project
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-30 13:37:37 -07:00
|
|
|
package com.android.launcher2;
|
2009-03-03 19:32:27 -08:00
|
|
|
|
2011-05-18 15:26:57 -07:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
2011-05-13 20:57:39 -07:00
|
|
|
import android.animation.Animator;
|
|
|
|
|
import android.animation.AnimatorListenerAdapter;
|
|
|
|
|
import android.animation.ValueAnimator;
|
|
|
|
|
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
2009-03-03 19:32:27 -08:00
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.res.Resources;
|
2011-05-02 15:36:58 -07:00
|
|
|
import android.graphics.Canvas;
|
2011-05-17 18:45:47 -07:00
|
|
|
import android.graphics.Color;
|
2009-03-03 19:32:27 -08:00
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
|
import android.view.LayoutInflater;
|
2011-05-18 15:26:57 -07:00
|
|
|
import android.view.View;
|
2009-03-03 19:32:27 -08:00
|
|
|
import android.view.ViewGroup;
|
2011-05-02 15:36:58 -07:00
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
import android.widget.TextView;
|
2009-03-03 19:32:27 -08:00
|
|
|
|
2010-03-04 13:03:17 -08:00
|
|
|
import com.android.launcher.R;
|
2011-05-02 15:36:58 -07:00
|
|
|
import com.android.launcher2.FolderInfo.FolderListener;
|
2010-03-04 13:03:17 -08:00
|
|
|
|
2009-03-03 19:32:27 -08:00
|
|
|
/**
|
|
|
|
|
* An icon that can appear on in the workspace representing an {@link UserFolder}.
|
|
|
|
|
*/
|
2011-05-02 15:36:58 -07:00
|
|
|
public class FolderIcon extends FrameLayout implements DropTarget, FolderListener {
|
2009-03-03 19:32:27 -08:00
|
|
|
private Launcher mLauncher;
|
2011-05-02 15:36:58 -07:00
|
|
|
Folder mFolder;
|
|
|
|
|
FolderInfo mInfo;
|
|
|
|
|
|
|
|
|
|
private static final int NUM_ITEMS_IN_PREVIEW = 4;
|
|
|
|
|
private static final float ICON_ANGLE = 15f;
|
2011-05-17 18:45:47 -07:00
|
|
|
private static final int CONSUMPTION_ANIMATION_DURATION = 100;
|
2011-05-17 16:28:09 -07:00
|
|
|
private static final float INNER_RING_GROWTH_FACTOR = 0.1f;
|
|
|
|
|
private static final float OUTER_RING_BASELINE_SCALE = 0.7f;
|
|
|
|
|
private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
|
2011-05-17 18:45:47 -07:00
|
|
|
private static final float INNER_RING_BASELINE_SCALE = 1.0f;
|
2009-03-03 19:32:27 -08:00
|
|
|
|
2011-05-17 16:28:09 -07:00
|
|
|
public static Drawable sFolderOuterRingDrawable = null;
|
2011-05-17 18:45:47 -07:00
|
|
|
public static Drawable sFolderInnerRingDrawable = null;
|
2011-05-17 16:28:09 -07:00
|
|
|
|
|
|
|
|
private int mOriginalWidth = -1;
|
|
|
|
|
private int mOriginalHeight = -1;
|
|
|
|
|
private int mOriginalX = -1;
|
|
|
|
|
private int mOriginalY = -1;
|
|
|
|
|
|
|
|
|
|
private int mFolderLocX;
|
|
|
|
|
private int mFolderLocY;
|
|
|
|
|
private float mOuterRingScale;
|
2011-05-17 18:45:47 -07:00
|
|
|
private float mInnerRingScale;
|
2011-05-13 20:57:39 -07:00
|
|
|
|
2009-03-03 19:32:27 -08:00
|
|
|
public FolderIcon(Context context, AttributeSet attrs) {
|
|
|
|
|
super(context, attrs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public FolderIcon(Context context) {
|
|
|
|
|
super(context);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-17 15:00:07 -07:00
|
|
|
public boolean isDropEnabled() {
|
2011-03-18 15:56:01 -07:00
|
|
|
final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
|
|
|
|
|
final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
|
|
|
|
|
final Workspace workspace = (Workspace) cellLayout.getParent();
|
|
|
|
|
return !workspace.isSmall();
|
2010-09-17 15:00:07 -07:00
|
|
|
}
|
|
|
|
|
|
2009-03-03 19:32:27 -08:00
|
|
|
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
|
2011-04-27 16:56:57 -07:00
|
|
|
FolderInfo folderInfo, IconCache iconCache) {
|
2009-03-03 19:32:27 -08:00
|
|
|
|
|
|
|
|
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
|
|
|
|
|
|
|
|
|
|
final Resources resources = launcher.getResources();
|
2011-05-13 20:57:39 -07:00
|
|
|
Drawable d = iconCache.getFullResIcon(resources, R.drawable.portal_ring_inner_holo);
|
2011-05-02 15:36:58 -07:00
|
|
|
icon.setBackgroundDrawable(d);
|
2009-03-03 19:32:27 -08:00
|
|
|
icon.setTag(folderInfo);
|
|
|
|
|
icon.setOnClickListener(launcher);
|
|
|
|
|
icon.mInfo = folderInfo;
|
|
|
|
|
icon.mLauncher = launcher;
|
2011-05-02 15:36:58 -07:00
|
|
|
|
|
|
|
|
Folder folder = Folder.fromXml(launcher);
|
|
|
|
|
folder.setDragController(launcher.getDragController());
|
|
|
|
|
folder.setLauncher(launcher);
|
2011-05-13 20:57:39 -07:00
|
|
|
folder.setFolderIcon(icon);
|
2011-05-02 15:36:58 -07:00
|
|
|
folder.bind(folderInfo);
|
|
|
|
|
icon.mFolder = folder;
|
|
|
|
|
|
|
|
|
|
folderInfo.addListener(icon);
|
2011-05-17 16:28:09 -07:00
|
|
|
if (sFolderOuterRingDrawable == null) {
|
|
|
|
|
sFolderOuterRingDrawable =
|
|
|
|
|
launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
|
|
|
|
|
}
|
2011-05-02 15:36:58 -07:00
|
|
|
|
2011-05-17 18:45:47 -07:00
|
|
|
if (sFolderInnerRingDrawable == null) {
|
|
|
|
|
sFolderInnerRingDrawable =
|
|
|
|
|
launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
|
|
|
|
|
}
|
2009-03-03 19:32:27 -08:00
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 16:28:09 -07:00
|
|
|
private boolean willAcceptItem(ItemInfo item) {
|
2009-03-03 19:32:27 -08:00
|
|
|
final int itemType = item.itemType;
|
2011-05-13 20:57:39 -07:00
|
|
|
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
|
|
|
|
|
itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
|
2011-05-17 16:28:09 -07:00
|
|
|
!mFolder.isFull() && item != mInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
|
|
|
|
|
DragView dragView, Object dragInfo) {
|
|
|
|
|
final ItemInfo item = (ItemInfo) dragInfo;
|
|
|
|
|
return willAcceptItem(item);
|
2009-03-03 19:32:27 -08:00
|
|
|
}
|
|
|
|
|
|
2011-04-11 17:22:04 -07:00
|
|
|
public void addItem(ShortcutInfo item) {
|
|
|
|
|
mInfo.add(item);
|
2011-05-02 15:36:58 -07:00
|
|
|
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
|
2011-04-11 17:22:04 -07:00
|
|
|
}
|
|
|
|
|
|
2009-08-04 16:04:30 -04:00
|
|
|
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
|
|
|
|
|
DragView dragView, Object dragInfo) {
|
2010-02-08 13:44:00 -08:00
|
|
|
ShortcutInfo item;
|
|
|
|
|
if (dragInfo instanceof ApplicationInfo) {
|
|
|
|
|
// Came from all apps -- make a copy
|
|
|
|
|
item = ((ApplicationInfo)dragInfo).makeShortcut();
|
|
|
|
|
} else {
|
|
|
|
|
item = (ShortcutInfo)dragInfo;
|
|
|
|
|
}
|
2011-04-12 16:29:25 -07:00
|
|
|
item.cellX = -1;
|
|
|
|
|
item.cellY = -1;
|
2011-04-11 17:22:04 -07:00
|
|
|
addItem(item);
|
2009-03-03 19:32:27 -08:00
|
|
|
}
|
|
|
|
|
|
2011-05-13 20:57:39 -07:00
|
|
|
void saveState(CellLayout.LayoutParams lp) {
|
|
|
|
|
mOriginalWidth = lp.width;
|
|
|
|
|
mOriginalHeight = lp.height;
|
|
|
|
|
mOriginalX = lp.x;
|
|
|
|
|
mOriginalY = lp.y;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 16:28:09 -07:00
|
|
|
private void animateToAcceptState() {
|
2011-05-13 20:57:39 -07:00
|
|
|
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
|
2011-05-17 16:28:09 -07:00
|
|
|
|
2011-05-17 18:45:47 -07:00
|
|
|
ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
|
|
|
|
|
va.setDuration(CONSUMPTION_ANIMATION_DURATION);
|
|
|
|
|
va.addUpdateListener(new AnimatorUpdateListener() {
|
2011-05-17 16:28:09 -07:00
|
|
|
public void onAnimationUpdate(ValueAnimator animation) {
|
|
|
|
|
final float percent = (Float) animation.getAnimatedValue();
|
|
|
|
|
mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
|
2011-05-17 18:45:47 -07:00
|
|
|
mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR;
|
2011-05-17 16:28:09 -07:00
|
|
|
mLauncher.getWorkspace().invalidate();
|
|
|
|
|
invalidate();
|
2011-05-13 20:57:39 -07:00
|
|
|
}
|
|
|
|
|
});
|
2011-05-17 18:45:47 -07:00
|
|
|
va.addListener(new AnimatorListenerAdapter() {
|
2011-05-13 20:57:39 -07:00
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
2011-05-17 18:45:47 -07:00
|
|
|
// Instead of setting the background drawable to null, we set the color to
|
|
|
|
|
// transparent. Setting the background drawable to null results in onDraw
|
|
|
|
|
// not getting called.
|
|
|
|
|
setBackgroundColor(Color.TRANSPARENT);
|
|
|
|
|
requestLayout();
|
2011-05-17 16:28:09 -07:00
|
|
|
}
|
|
|
|
|
});
|
2011-05-17 18:45:47 -07:00
|
|
|
va.start();
|
|
|
|
|
}
|
2011-05-17 16:28:09 -07:00
|
|
|
|
2011-05-17 18:45:47 -07:00
|
|
|
private void animateToNaturalState() {
|
|
|
|
|
ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
|
|
|
|
|
va.setDuration(CONSUMPTION_ANIMATION_DURATION);
|
|
|
|
|
va.addUpdateListener(new AnimatorUpdateListener() {
|
2011-05-17 16:28:09 -07:00
|
|
|
public void onAnimationUpdate(ValueAnimator animation) {
|
|
|
|
|
final float percent = (Float) animation.getAnimatedValue();
|
|
|
|
|
mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
|
|
|
|
|
- percent * OUTER_RING_GROWTH_FACTOR;
|
2011-05-17 18:45:47 -07:00
|
|
|
mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR
|
|
|
|
|
- percent * INNER_RING_GROWTH_FACTOR;
|
2011-05-17 16:28:09 -07:00
|
|
|
mLauncher.getWorkspace().invalidate();
|
2011-05-17 18:45:47 -07:00
|
|
|
invalidate();
|
2011-05-13 20:57:39 -07:00
|
|
|
}
|
|
|
|
|
});
|
2011-05-17 18:45:47 -07:00
|
|
|
va.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
|
setBackgroundDrawable(sFolderInnerRingDrawable);
|
|
|
|
|
mLauncher.getWorkspace().hideFolderAccept(FolderIcon.this);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
va.start();
|
2009-03-03 19:32:27 -08:00
|
|
|
}
|
2010-07-13 17:50:32 -07:00
|
|
|
|
2011-05-17 16:28:09 -07:00
|
|
|
private void determineFolderLocationInWorkspace() {
|
|
|
|
|
int tvLocation[] = new int[2];
|
|
|
|
|
int wsLocation[] = new int[2];
|
|
|
|
|
getLocationOnScreen(tvLocation);
|
|
|
|
|
mLauncher.getWorkspace().getLocationOnScreen(wsLocation);
|
|
|
|
|
mFolderLocX = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2;
|
|
|
|
|
mFolderLocY = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
|
|
|
|
|
DragView dragView, Object dragInfo) {
|
|
|
|
|
if (!willAcceptItem((ItemInfo) dragInfo)) return;
|
|
|
|
|
determineFolderLocationInWorkspace();
|
|
|
|
|
mLauncher.getWorkspace().showFolderAccept(this);
|
|
|
|
|
animateToAcceptState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
|
|
|
|
|
DragView dragView, Object dragInfo) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
|
|
|
|
|
DragView dragView, Object dragInfo) {
|
|
|
|
|
if (!willAcceptItem((ItemInfo) dragInfo)) return;
|
|
|
|
|
animateToNaturalState();
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-13 17:50:32 -07:00
|
|
|
@Override
|
|
|
|
|
public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
|
|
|
|
|
DragView dragView, Object dragInfo) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2011-05-02 15:36:58 -07:00
|
|
|
|
2011-05-17 16:28:09 -07:00
|
|
|
public void getFolderLocation(int[] loc) {
|
|
|
|
|
loc[0] = mFolderLocX;
|
|
|
|
|
loc[1] = mFolderLocY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float getOuterRingScale() {
|
|
|
|
|
return mOuterRingScale;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 18:45:47 -07:00
|
|
|
public float getInnerRingScale() {
|
|
|
|
|
return mInnerRingScale;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-02 15:36:58 -07:00
|
|
|
@Override
|
|
|
|
|
protected void onDraw(Canvas canvas) {
|
|
|
|
|
if (mFolder == null) return;
|
|
|
|
|
if (mFolder.getItemCount() == 0) return;
|
|
|
|
|
|
|
|
|
|
canvas.save();
|
|
|
|
|
TextView v = (TextView) mFolder.getItemAt(0);
|
|
|
|
|
Drawable d = v.getCompoundDrawables()[1];
|
|
|
|
|
|
2011-05-17 16:28:09 -07:00
|
|
|
if (mOriginalWidth < 0 || mOriginalHeight < 0) {
|
|
|
|
|
mOriginalWidth = getMeasuredWidth();
|
|
|
|
|
mOriginalHeight = getMeasuredHeight();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int xShift = (mOriginalWidth - d.getIntrinsicWidth()) / 2;
|
|
|
|
|
int yShift = (mOriginalHeight - d.getIntrinsicHeight()) / 2;
|
|
|
|
|
canvas.translate(xShift, yShift);
|
2011-05-02 15:36:58 -07:00
|
|
|
|
2011-05-18 15:26:57 -07:00
|
|
|
ArrayList<View> items = mFolder.getItemsInReadingOrder();
|
|
|
|
|
int firstItemIndex = Math.max(0, items.size() - NUM_ITEMS_IN_PREVIEW);
|
2011-05-18 17:14:15 -07:00
|
|
|
for (int i = firstItemIndex; i < items.size(); i++) {
|
2011-05-18 15:26:57 -07:00
|
|
|
v = (TextView) items.get(i);
|
2011-05-02 15:36:58 -07:00
|
|
|
d = v.getCompoundDrawables()[1];
|
|
|
|
|
|
2011-05-17 18:45:47 -07:00
|
|
|
canvas.translate(d.getIntrinsicWidth() / 2, d.getIntrinsicHeight() / 2);
|
2011-05-18 15:26:57 -07:00
|
|
|
canvas.rotate(i == firstItemIndex ? ICON_ANGLE : -ICON_ANGLE);
|
2011-05-17 18:45:47 -07:00
|
|
|
canvas.translate(-d.getIntrinsicWidth() / 2, -d.getIntrinsicHeight() / 2);
|
|
|
|
|
|
2011-05-02 15:36:58 -07:00
|
|
|
if (d != null) {
|
|
|
|
|
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
|
|
|
|
|
d.draw(canvas);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
canvas.restore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onAdd(ShortcutInfo item) {
|
|
|
|
|
invalidate();
|
|
|
|
|
requestLayout();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onRemove(ShortcutInfo item) {
|
|
|
|
|
invalidate();
|
|
|
|
|
requestLayout();
|
|
|
|
|
}
|
2009-03-03 19:32:27 -08:00
|
|
|
}
|