Changing folders to use CellLayouts
Change-Id: Ic80bece18855a4f5d2476c224ef66f035ac7c97b
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index ac1a4bd..636b041 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -1520,6 +1520,14 @@
}
}
+ public boolean isOccupied(int x, int y) {
+ if (x < mCountX && y < mCountY) {
+ return mOccupied[x][y];
+ } else {
+ throw new RuntimeException("Position exceeds the bound of this CellLayout");
+ }
+ }
+
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new CellLayout.LayoutParams(getContext(), attrs);
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 059e73d..33a1cd3 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -37,7 +37,6 @@
public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
OnItemClickListener, OnClickListener, View.OnLongClickListener {
- protected AbsListView mContent;
protected DragController mDragController;
protected Launcher mLauncher;
@@ -66,10 +65,6 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mContent = (AbsListView) findViewById(R.id.folder_content);
- mContent.setOnItemClickListener(this);
- mContent.setOnItemLongClickListener(this);
-
mCloseButton = (Button) findViewById(R.id.folder_close);
mCloseButton.setOnClickListener(this);
mCloseButton.setOnLongClickListener(this);
@@ -121,18 +116,7 @@
public void onDragViewVisible() {
}
- /**
- * Sets the adapter used to populate the content area. The adapter must only
- * contains ShortcutInfo items.
- *
- * @param adapter The list of applications to display in the folder.
- */
- void setContentAdapter(BaseAdapter adapter) {
- mContent.setAdapter(adapter);
- }
-
void notifyDataSetChanged() {
- ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
}
void setLauncher(Launcher launcher) {
@@ -146,10 +130,7 @@
return mInfo;
}
- // When the folder opens, we need to refresh the GridView's selection by
- // forcing a layout
void onOpen() {
- mContent.requestLayout();
}
void onClose() {
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index a64b550..1122d77 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -91,6 +91,8 @@
} else {
item = (ShortcutInfo)dragInfo;
}
+ item.cellX = -1;
+ item.cellY = -1;
addItem(item);
}
diff --git a/src/com/android/launcher2/LiveFolder.java b/src/com/android/launcher2/LiveFolder.java
index 07a295f..b692953 100644
--- a/src/com/android/launcher2/LiveFolder.java
+++ b/src/com/android/launcher2/LiveFolder.java
@@ -22,10 +22,12 @@
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
+import android.widget.BaseAdapter;
import android.net.Uri;
import android.provider.LiveFolders;
import android.os.AsyncTask;
import android.database.Cursor;
+import android.widget.GridView;
import java.lang.ref.WeakReference;
@@ -33,6 +35,7 @@
public class LiveFolder extends Folder {
private AsyncTask<LiveFolderInfo,Void,Cursor> mLoadingTask;
+ protected GridView mContent;
public LiveFolder(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -44,6 +47,15 @@
return (LiveFolder) LayoutInflater.from(context).inflate(layout, null);
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mContent = (GridView) findViewById(R.id.folder_content);
+ mContent.setOnItemClickListener(this);
+ mContent.setOnItemLongClickListener(this);
+ }
+
private static boolean isDisplayModeList(FolderInfo folderInfo) {
return ((LiveFolderInfo) folderInfo).displayMode ==
LiveFolders.DISPLAY_MODE_LIST;
@@ -68,6 +80,21 @@
}
}
+ /**
+ * Sets the adapter used to populate the content area. The adapter must only
+ * contains ShortcutInfo items.
+ *
+ * @param adapter The list of applications to display in the folder.
+ */
+ void setContentAdapter(BaseAdapter adapter) {
+ mContent.setAdapter(adapter);
+ }
+
+ @Override
+ void notifyDataSetChanged() {
+ ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
+ }
+
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
return false;
@@ -84,6 +111,9 @@
@Override
void onOpen() {
super.onOpen();
+ // When the folder opens, we need to refresh the GridView's selection by
+ // forcing a layout
+ mContent.requestLayout();
requestFocus();
}
diff --git a/src/com/android/launcher2/UserFolder.java b/src/com/android/launcher2/UserFolder.java
index 251b3f9..b800b07 100644
--- a/src/com/android/launcher2/UserFolder.java
+++ b/src/com/android/launcher2/UserFolder.java
@@ -1,11 +1,18 @@
package com.android.launcher2;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.GridView;
+import android.widget.TextView;
import com.android.launcher.R;
+import java.util.ArrayList;
/**
* Folder which contains applications or shortcuts chosen by the user.
@@ -14,8 +21,21 @@
public class UserFolder extends Folder implements DropTarget {
private static final String TAG = "Launcher.UserFolder";
+ protected CellLayout mContent;
+ private final LayoutInflater mInflater;
+ private final IconCache mIconCache;
+
public UserFolder(Context context, AttributeSet attrs) {
super(context, attrs);
+ mInflater = LayoutInflater.from(context);
+ mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mContent = (CellLayout) findViewById(R.id.folder_content);
}
/**
@@ -29,6 +49,48 @@
return (UserFolder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
}
+ @Override
+ 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 void onClick(View v) {
+ 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 {
+ super.onClick(v);
+ }
+ }
+
+ public boolean onLongClick(View v) {
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ // refactor this code from Folder
+ ShortcutInfo item = (ShortcutInfo) tag;
+ if (!v.isInTouchMode()) {
+ return false;
+ }
+
+ mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
+ mLauncher.closeFolder(this);
+ mDragItem = item;
+
+ return true;
+ } else {
+ return super.onLongClick(v);
+ }
+ }
+
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
@@ -44,11 +106,45 @@
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;
}
- ((ShortcutsAdapter)mContent.getAdapter()).add(item);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
+ findAndSetEmptyCells(item);
+ ((UserFolderInfo)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,
@@ -66,8 +162,7 @@
@Override
public void onDropCompleted(View target, Object dragInfo, boolean success) {
if (success) {
- ShortcutsAdapter adapter = (ShortcutsAdapter)mContent.getAdapter();
- adapter.remove(mDragItem);
+ ((UserFolderInfo)mInfo).remove(mDragItem);
}
}
@@ -77,14 +172,24 @@
void bind(FolderInfo info) {
super.bind(info);
- setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
+ ArrayList<ShortcutInfo> children = ((UserFolderInfo)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));
+ }
}
- // When the folder opens, we need to refresh the GridView's selection by
- // forcing a layout
@Override
void onOpen() {
super.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();
}