summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher2/Folder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher2/Folder.java')
-rw-r--r--src/com/android/launcher2/Folder.java298
1 files changed, 284 insertions, 14 deletions
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 7eb3bb162..4c8d03a4a 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -16,14 +16,25 @@
package com.android.launcher2;
+import java.util.ArrayList;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
+import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
@@ -33,14 +44,14 @@ import com.android.launcher.R;
* Represents a set of icons chosen by the user or generated by the system.
*/
public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
- OnItemClickListener, OnClickListener, View.OnLongClickListener {
+ OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget {
protected DragController mDragController;
-
+
protected Launcher mLauncher;
protected Button mCloseButton;
-
+
protected FolderInfo mInfo;
/**
@@ -48,6 +59,19 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
*/
protected ShortcutInfo mDragItem;
+ private static final String TAG = "Launcher.Folder";
+
+ static final int STATE_NONE = -1;
+ static final int STATE_SMALL = 0;
+ static final int STATE_ANIMATING = 1;
+ static final int STATE_OPEN = 2;
+
+ private int mExpandDuration;
+ protected CellLayout mContent;
+ private final LayoutInflater mInflater;
+ private final IconCache mIconCache;
+ private int mState = STATE_NONE;
+
/**
* Used to inflate the Workspace from XML.
*
@@ -57,6 +81,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
public Folder(Context context, AttributeSet attrs) {
super(context, attrs);
setAlwaysDrawnWithCacheEnabled(false);
+ mInflater = LayoutInflater.from(context);
+ mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
+ mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
}
@Override
@@ -66,6 +93,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
mCloseButton = (Button) findViewById(R.id.folder_close);
mCloseButton.setOnClickListener(this);
mCloseButton.setOnLongClickListener(this);
+ mContent = (CellLayout) findViewById(R.id.folder_content);
}
public void onItemClick(AdapterView parent, View v, int position, long id) {
@@ -78,12 +106,38 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
public void onClick(View v) {
- mLauncher.closeFolder(this);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ // refactor this code from Folder
+ ShortcutInfo item = (ShortcutInfo) tag;
+ int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+ item.intent.setSourceBounds(new Rect(pos[0], pos[1],
+ pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+ mLauncher.startActivitySafely(item.intent, item);
+ } else {
+ mLauncher.closeFolder(this);
+ }
}
public boolean onLongClick(View v) {
- mLauncher.closeFolder(this);
- mLauncher.showRenameDialog(mInfo);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ // refactor this code from Folder
+ ShortcutInfo item = (ShortcutInfo) tag;
+ if (!v.isInTouchMode()) {
+ return false;
+ }
+
+ mLauncher.getWorkspace().onDragStartedWithItem(v);
+ mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
+
+ mLauncher.closeFolder(this);
+ mDragItem = item;
+ } else {
+ mLauncher.closeFolder(this);
+ mLauncher.showRenameDialog(mInfo);
+ }
return true;
}
@@ -105,17 +159,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
mDragController = dragController;
}
- @Override
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
- }
-
- @Override
public void onDragViewVisible() {
}
- void notifyDataSetChanged() {
- }
-
void setLauncher(Launcher launcher) {
mLauncher = launcher;
}
@@ -128,6 +174,11 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
void onOpen() {
+ // When the folder opens, we need to refresh the GridView's selection by
+ // forcing a layout
+ // TODO: find out if this is still necessary
+ mContent.requestLayout();
+ requestFocus();
}
void onClose() {
@@ -138,5 +189,224 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
void bind(FolderInfo info) {
mInfo = info;
mCloseButton.setText(info.title);
+ ArrayList<ShortcutInfo> children = info.contents;
+ for (int i = 0; i < children.size(); i++) {
+ ShortcutInfo child = (ShortcutInfo) children.get(i);
+ if ((child.cellX == -1 && child.cellY == -1) ||
+ mContent.isOccupied(child.cellX, child.cellY)) {
+ findAndSetEmptyCells(child);
+ }
+ createAndAddShortcut((ShortcutInfo) children.get(i));
+ }
+ }
+
+ /**
+ * Creates a new UserFolder, inflated from R.layout.user_folder.
+ *
+ * @param context The application's context.
+ *
+ * @return A new UserFolder.
+ */
+ static Folder fromXml(Context context) {
+ return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
+ }
+
+ /**
+ * This method is intended to make the UserFolder to be visually identical in size and position
+ * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
+ */
+ private void positionAndSizeAsIcon() {
+ if (!(getParent() instanceof CellLayoutChildren)) return;
+
+ CellLayoutChildren clc = (CellLayoutChildren) getParent();
+ CellLayout cellLayout = (CellLayout) clc.getParent();
+
+ FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
+ CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ lp.width = iconLp.width;
+ lp.height = iconLp.height;
+ lp.x = iconLp.x;
+ lp.y = iconLp.y;
+
+ mContent.setAlpha(0f);
+ mState = STATE_SMALL;
+ }
+
+ public void animateOpen() {
+ if (mState != STATE_SMALL) {
+ positionAndSizeAsIcon();
+ }
+ if (!(getParent() instanceof CellLayoutChildren)) return;
+
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ CellLayoutChildren clc = (CellLayoutChildren) getParent();
+ CellLayout cellLayout = (CellLayout) clc.getParent();
+ Rect r = cellLayout.getContentRect(null);
+
+ PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", r.width());
+ PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", r.height());
+ PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", 0);
+ PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", 0);
+
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+ oa.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ requestLayout();
+ }
+ });
+
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
+ ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
+
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(oa, oaContentAlpha);
+ set.setDuration(mExpandDuration);
+ set.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mState = STATE_ANIMATING;
+ }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mState = STATE_SMALL;
+ }
+ });
+ set.start();
+ }
+
+ public void animateClosed() {
+ if (!(getParent() instanceof CellLayoutChildren)) return;
+
+ CellLayoutChildren clc = (CellLayoutChildren) getParent();
+ final CellLayout cellLayout = (CellLayout) clc.getParent();
+
+ FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
+ CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
+ PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
+ PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
+ PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
+
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+ oa.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ requestLayout();
+ }
+ });
+
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
+ ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
+
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(oa, oaContentAlpha);
+ set.setDuration(mExpandDuration);
+
+ set.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ cellLayout.removeViewWithoutMarkingCells(Folder.this);
+ mState = STATE_OPEN;
+ }
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mState = STATE_ANIMATING;
+ }
+ });
+ set.start();
+ }
+
+ void notifyDataSetChanged() {
+ // recreate all the children if the data set changes under us. We may want to do this more
+ // intelligently (ie just removing the views that should no longer exist)
+ mContent.removeAllViewsInLayout();
+ bind(mInfo);
+ }
+
+ public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
+ DragView dragView, Object dragInfo) {
+ final ItemInfo item = (ItemInfo) dragInfo;
+ final int itemType = item.itemType;
+ return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+ itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
+ && item.container != mInfo.id;
+ }
+
+ public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
+ DragView dragView, Object dragInfo) {
+ ShortcutInfo item;
+ if (dragInfo instanceof ApplicationInfo) {
+ // Came from all apps -- make a copy
+ item = ((ApplicationInfo)dragInfo).makeShortcut();
+ item.spanX = 1;
+ item.spanY = 1;
+ } else {
+ item = (ShortcutInfo)dragInfo;
+ }
+ findAndSetEmptyCells(item);
+ mInfo.add(item);
+ createAndAddShortcut(item);
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ }
+
+ protected boolean findAndSetEmptyCells(ShortcutInfo item) {
+ int[] emptyCell = new int[2];
+ if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
+ item.cellX = emptyCell[0];
+ item.cellY = emptyCell[1];
+ LauncherModel.addOrMoveItemInDatabase(
+ mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected void createAndAddShortcut(ShortcutInfo item) {
+ final TextView textView =
+ (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
+ textView.setText(item.title);
+ textView.setTag(item);
+
+ textView.setOnClickListener(this);
+ textView.setOnLongClickListener(this);
+
+ CellLayout.LayoutParams lp =
+ new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
+ boolean insert = false;
+ mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
+ }
+
+ public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
+ DragView dragView, Object dragInfo) {
+ }
+
+ 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) {
+ }
+
+ public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ if (success) {
+ mInfo.remove(mDragItem);
+ }
+ }
+
+ public boolean isDropEnabled() {
+ return true;
+ }
+
+ public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
+ DragView dragView, Object dragInfo) {
+ return null;
}
}