Adding support for drag and drop of folders and shortcuts.
also:
- Long press on empty space on workspace now brings up customization tray
- Fixed: while dragging, items appeared to be dropping on folders two cells to the right
- Fixed: Disabling drops on folders when the workspace is shrunken
- Fixed: account for scaling of dragged items when checking if they overlap
with shrunken workspace screens
- Making folder icons dimmable to match shortcuts and widgets
- When deciding with shrunken workspace screen we're dragging to, we now use the closest screen rather than the one that has been overlapped the most
- Refactored drag/add mechanism, removing array of occupied cells from CellInfo
- Removed dead code/variables
This commit is contained in:
@@ -511,4 +511,8 @@ public class AllAppsPagedView extends PagedView
|
||||
@Override
|
||||
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
|
||||
DragView dragView, Object dragInfo) {}
|
||||
|
||||
public boolean isDropEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,10 @@ public class ApplicationInfoDropTarget extends ImageView implements DropTarget,
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDropEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onDragEnd() {
|
||||
if (mActive) {
|
||||
mActive = false;
|
||||
|
||||
@@ -40,8 +40,6 @@ import java.util.Arrays;
|
||||
public class CellLayout extends ViewGroup {
|
||||
static final String TAG = "CellLayout";
|
||||
|
||||
private boolean mPortrait;
|
||||
|
||||
private int mCellWidth;
|
||||
private int mCellHeight;
|
||||
|
||||
@@ -90,9 +88,6 @@ public class CellLayout extends ViewGroup {
|
||||
// When a drag operation is in progress, holds the nearest cell to the touch point
|
||||
private final int[] mDragCell = new int[2];
|
||||
|
||||
private boolean mDirtyTag;
|
||||
private boolean mLastDownOnOccupiedCell = false;
|
||||
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
|
||||
public CellLayout(Context context) {
|
||||
@@ -135,6 +130,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
mCountX = LauncherModel.getCellCountX();
|
||||
mCountY = LauncherModel.getCellCountY();
|
||||
mOccupied = new boolean[mCountX][mCountY];
|
||||
|
||||
a.recycle();
|
||||
|
||||
@@ -214,14 +210,59 @@ public class CellLayout extends ViewGroup {
|
||||
// We might be in the middle or end of shrinking/fading to a dimmed view
|
||||
// Make sure this view's alpha is set the same as all the rest of the views
|
||||
child.setAlpha(getAlpha());
|
||||
|
||||
addView(child, index, lp);
|
||||
|
||||
markCellsAsOccupiedForView(child);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllViews() {
|
||||
clearOccupiedCells();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllViewsInLayout() {
|
||||
clearOccupiedCells();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeView(View view) {
|
||||
markCellsAsUnoccupiedForView(view);
|
||||
super.removeView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewAt(int index) {
|
||||
markCellsAsUnoccupiedForView(getChildAt(index));
|
||||
super.removeViewAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewInLayout(View view) {
|
||||
markCellsAsUnoccupiedForView(view);
|
||||
super.removeViewInLayout(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViews(int start, int count) {
|
||||
for (int i = start; i < start + count; i++) {
|
||||
markCellsAsUnoccupiedForView(getChildAt(i));
|
||||
}
|
||||
super.removeViews(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewsInLayout(int start, int count) {
|
||||
for (int i = start; i < start + count; i++) {
|
||||
markCellsAsUnoccupiedForView(getChildAt(i));
|
||||
}
|
||||
super.removeViewsInLayout(start, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestChildFocus(View child, View focused) {
|
||||
super.requestChildFocus(child, focused);
|
||||
@@ -258,45 +299,24 @@ public class CellLayout extends ViewGroup {
|
||||
cellInfo.cellY = lp.cellY;
|
||||
cellInfo.spanX = lp.cellHSpan;
|
||||
cellInfo.spanY = lp.cellVSpan;
|
||||
cellInfo.intersectX = lp.cellX;
|
||||
cellInfo.intersectY = lp.cellY;
|
||||
cellInfo.valid = true;
|
||||
found = true;
|
||||
mDirtyTag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLastDownOnOccupiedCell = found;
|
||||
|
||||
if (!found) {
|
||||
final int cellXY[] = mTmpCellXY;
|
||||
pointToCellExact(x, y, cellXY);
|
||||
|
||||
final boolean portrait = mPortrait;
|
||||
final int xCount = mCountX;
|
||||
final int yCount = mCountY;
|
||||
|
||||
final boolean[][] occupied = mOccupied;
|
||||
findOccupiedCells(xCount, yCount, occupied, null, true);
|
||||
|
||||
cellInfo.cell = null;
|
||||
cellInfo.cellX = cellXY[0];
|
||||
cellInfo.cellY = cellXY[1];
|
||||
cellInfo.spanX = 1;
|
||||
cellInfo.spanY = 1;
|
||||
cellInfo.intersectX = cellXY[0];
|
||||
cellInfo.intersectY = cellXY[1];
|
||||
cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < xCount &&
|
||||
cellXY[1] < yCount && !occupied[cellXY[0]][cellXY[1]];
|
||||
|
||||
// Instead of finding the interesting vacant cells here, wait until a
|
||||
// caller invokes getTag() to retrieve the result. Finding the vacant
|
||||
// cells is a bit expensive and can generate many new objects, it's
|
||||
// therefore better to defer it until we know we actually need it.
|
||||
|
||||
mDirtyTag = true;
|
||||
cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < mCountX &&
|
||||
cellXY[1] < mCountY && !mOccupied[cellXY[0]][cellXY[1]];
|
||||
}
|
||||
setTag(cellInfo);
|
||||
}
|
||||
@@ -319,7 +339,6 @@ public class CellLayout extends ViewGroup {
|
||||
cellInfo.spanX = 0;
|
||||
cellInfo.spanY = 0;
|
||||
cellInfo.valid = false;
|
||||
mDirtyTag = false;
|
||||
setTag(cellInfo);
|
||||
}
|
||||
|
||||
@@ -328,31 +347,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
@Override
|
||||
public CellInfo getTag() {
|
||||
final CellInfo info = (CellInfo) super.getTag();
|
||||
if (mDirtyTag && info.valid) {
|
||||
final int xCount = mCountX;
|
||||
final int yCount = mCountY;
|
||||
|
||||
final boolean[][] occupied = mOccupied;
|
||||
findOccupiedCells(xCount, yCount, occupied, null, true);
|
||||
|
||||
info.updateOccupiedCells(occupied, mCountX, mCountY);
|
||||
|
||||
mDirtyTag = false;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the column 'x' is empty from rows 'top' to 'bottom', inclusive.
|
||||
*/
|
||||
private static boolean isColumnEmpty(int x, int top, int bottom, boolean[][] occupied) {
|
||||
for (int y = top; y <= bottom; y++) {
|
||||
if (occupied[x][y]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return (CellInfo) super.getTag();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,42 +362,6 @@ public class CellLayout extends ViewGroup {
|
||||
return true;
|
||||
}
|
||||
|
||||
CellInfo updateOccupiedCells(boolean[] occupiedCells, View ignoreView) {
|
||||
final int xCount = mCountX;
|
||||
final int yCount = mCountY;
|
||||
|
||||
boolean[][] occupied = mOccupied;
|
||||
|
||||
if (occupiedCells != null) {
|
||||
for (int y = 0; y < yCount; y++) {
|
||||
for (int x = 0; x < xCount; x++) {
|
||||
occupied[x][y] = occupiedCells[y * xCount + x];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
findOccupiedCells(xCount, yCount, occupied, ignoreView, true);
|
||||
}
|
||||
|
||||
CellInfo cellInfo = new CellInfo();
|
||||
|
||||
cellInfo.cellX = -1;
|
||||
cellInfo.cellY = -1;
|
||||
cellInfo.intersectX = -1;
|
||||
cellInfo.intersectY = -1;
|
||||
cellInfo.spanY = 0;
|
||||
cellInfo.spanX = 0;
|
||||
cellInfo.screen = mCellInfo.screen;
|
||||
|
||||
cellInfo.updateOccupiedCells(occupied, mCountX, mCountY);
|
||||
|
||||
cellInfo.valid = cellInfo.existsEmptyCell();
|
||||
|
||||
// Assume the caller will perform their own cell searching, otherwise we
|
||||
// risk causing an unnecessary rebuild after findCellForSpan()
|
||||
|
||||
return cellInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a point, return the cell that strictly encloses that point
|
||||
* @param x X coordinate of the point
|
||||
@@ -492,19 +451,13 @@ public class CellLayout extends ViewGroup {
|
||||
final int cellWidth = mCellWidth;
|
||||
final int cellHeight = mCellHeight;
|
||||
|
||||
if (mOccupied == null) {
|
||||
mOccupied = new boolean[mCountX][mCountY];
|
||||
}
|
||||
|
||||
int numWidthGaps = mCountX - 1;
|
||||
int numHeightGaps = mCountY - 1;
|
||||
|
||||
int vSpaceLeft = heightSpecSize - mTopPadding
|
||||
- mBottomPadding - (cellHeight * mCountY);
|
||||
int vSpaceLeft = heightSpecSize - mTopPadding - mBottomPadding - (cellHeight * mCountY);
|
||||
mHeightGap = vSpaceLeft / numHeightGaps;
|
||||
|
||||
int hSpaceLeft = widthSpecSize - mLeftPadding
|
||||
- mRightPadding - (cellWidth * mCountX);
|
||||
int hSpaceLeft = widthSpecSize - mLeftPadding - mRightPadding - (cellWidth * mCountX);
|
||||
mWidthGap = hSpaceLeft / numWidthGaps;
|
||||
|
||||
// center it around the min gaps
|
||||
@@ -519,8 +472,7 @@ public class CellLayout extends ViewGroup {
|
||||
lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
|
||||
mLeftPadding, mTopPadding);
|
||||
|
||||
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width,
|
||||
MeasureSpec.EXACTLY);
|
||||
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
|
||||
int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
|
||||
MeasureSpec.EXACTLY);
|
||||
|
||||
@@ -538,7 +490,7 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
public void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int count = getChildCount();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -621,15 +573,29 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isVacant(int originX, int originY, int spanX, int spanY) {
|
||||
private boolean isVacantIgnoring(
|
||||
int originX, int originY, int spanX, int spanY, View ignoreView) {
|
||||
if (ignoreView != null) {
|
||||
markCellsAsUnoccupiedForView(ignoreView);
|
||||
}
|
||||
for (int i = 0; i < spanY; i++) {
|
||||
if (!isRowEmpty(originY + i, originX, originX + spanX - 1, mOccupied)) {
|
||||
if (ignoreView != null) {
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ignoreView != null) {
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isVacant(int originX, int originY, int spanX, int spanY) {
|
||||
return isVacantIgnoring(originX, originY, spanX, spanY, null);
|
||||
}
|
||||
|
||||
public View getChildAt(int x, int y) {
|
||||
final int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -687,7 +653,8 @@ public class CellLayout extends ViewGroup {
|
||||
result[1] = Math.max(0, result[1]); // Snap to top
|
||||
}
|
||||
|
||||
void visualizeDropLocation(View view, int originX, int originY, int spanX, int spanY) {
|
||||
void visualizeDropLocation(
|
||||
View view, int originX, int originY, int spanX, int spanY, View draggedItem) {
|
||||
final int[] originCell = mDragCell;
|
||||
final int[] cellXY = mTmpCellXY;
|
||||
estimateDropCell(originX, originY, spanX, spanY, cellXY);
|
||||
@@ -709,12 +676,8 @@ public class CellLayout extends ViewGroup {
|
||||
bottomRight[0] += mCellWidth;
|
||||
bottomRight[1] += mCellHeight;
|
||||
|
||||
final int countX = mCountX;
|
||||
final int countY = mCountY;
|
||||
// TODO: It's not necessary to do this every time, but it's not especially expensive
|
||||
findOccupiedCells(countX, countY, mOccupied, view, false);
|
||||
|
||||
boolean vacant = isVacant(originCell[0], originCell[1], spanX, spanY);
|
||||
boolean vacant =
|
||||
isVacantIgnoring(originCell[0], originCell[1], spanX, spanY, draggedItem);
|
||||
mDragRectDrawable = vacant ? mVacantDrawable : mOccupiedDrawable;
|
||||
|
||||
// mDragRect will be rendered in onDraw()
|
||||
@@ -736,8 +699,7 @@ public class CellLayout extends ViewGroup {
|
||||
* @return The X, Y cell of a vacant area that can contain this object,
|
||||
* nearest the requested location.
|
||||
*/
|
||||
int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY,
|
||||
CellInfo vacantCells, int[] recycle) {
|
||||
int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY, int[] recycle) {
|
||||
|
||||
// Keep track of best-scoring drop area
|
||||
final int[] bestXY = recycle != null ? recycle : new int[2];
|
||||
@@ -777,10 +739,130 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
boolean existsEmptyCell() {
|
||||
return findCellForSpan(null, 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a drag and drop operation has finished (successfully or not).
|
||||
* Finds the upper-left coordinate of the first rectangle in the grid that can
|
||||
* hold a cell of the specified dimensions. If intersectX and intersectY are not -1,
|
||||
* then this method will only return coordinates for rectangles that contain the cell
|
||||
* (intersectX, intersectY)
|
||||
*
|
||||
* @param cellXY The array that will contain the position of a vacant cell if such a cell
|
||||
* can be found.
|
||||
* @param spanX The horizontal span of the cell we want to find.
|
||||
* @param spanY The vertical span of the cell we want to find.
|
||||
*
|
||||
* @return True if a vacant cell of the specified dimension was found, false otherwise.
|
||||
*/
|
||||
void onDragComplete() {
|
||||
boolean findCellForSpan(int[] cellXY, int spanX, int spanY) {
|
||||
return findCellForSpanThatIntersectsIgnoring(cellXY, spanX, spanY, -1, -1, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like above, but ignores any cells occupied by the item "ignoreView"
|
||||
*
|
||||
* @param cellXY The array that will contain the position of a vacant cell if such a cell
|
||||
* can be found.
|
||||
* @param spanX The horizontal span of the cell we want to find.
|
||||
* @param spanY The vertical span of the cell we want to find.
|
||||
* @param ignoreView The home screen item we should treat as not occupying any space
|
||||
* @return
|
||||
*/
|
||||
boolean findCellForSpanIgnoring(int[] cellXY, int spanX, int spanY, View ignoreView) {
|
||||
return findCellForSpanThatIntersectsIgnoring(cellXY, spanX, spanY, -1, -1, ignoreView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like above, but if intersectX and intersectY are not -1, then this method will try to
|
||||
* return coordinates for rectangles that contain the cell [intersectX, intersectY]
|
||||
*
|
||||
* @param spanX The horizontal span of the cell we want to find.
|
||||
* @param spanY The vertical span of the cell we want to find.
|
||||
* @param ignoreView The home screen item we should treat as not occupying any space
|
||||
* @param intersectX The X coordinate of the cell that we should try to overlap
|
||||
* @param intersectX The Y coordinate of the cell that we should try to overlap
|
||||
*
|
||||
* @return True if a vacant cell of the specified dimension was found, false otherwise.
|
||||
*/
|
||||
boolean findCellForSpanThatIntersects(int[] cellXY, int spanX, int spanY,
|
||||
int intersectX, int intersectY) {
|
||||
return findCellForSpanThatIntersectsIgnoring(
|
||||
cellXY, spanX, spanY, intersectX, intersectY, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The superset of the above two methods
|
||||
*/
|
||||
boolean findCellForSpanThatIntersectsIgnoring(int[] cellXY, int spanX, int spanY,
|
||||
int intersectX, int intersectY, View ignoreView) {
|
||||
if (ignoreView != null) {
|
||||
markCellsAsUnoccupiedForView(ignoreView);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int startX = 0;
|
||||
if (intersectX >= 0) {
|
||||
startX = Math.max(startX, intersectX - (spanX - 1));
|
||||
}
|
||||
int endX = mCountX - (spanX - 1);
|
||||
if (intersectX >= 0) {
|
||||
endX = Math.min(endX, intersectX + (spanX - 1) + (spanX == 1 ? 1 : 0));
|
||||
}
|
||||
int startY = 0;
|
||||
if (intersectY >= 0) {
|
||||
startY = Math.max(startY, intersectY - (spanY - 1));
|
||||
}
|
||||
int endY = mCountY - (spanY - 1);
|
||||
if (intersectY >= 0) {
|
||||
endY = Math.min(endY, intersectY + (spanY - 1) + (spanY == 1 ? 1 : 0));
|
||||
}
|
||||
|
||||
for (int x = startX; x < endX; x++) {
|
||||
inner:
|
||||
for (int y = startY; y < endY; y++) {
|
||||
for (int i = 0; i < spanX; i++) {
|
||||
for (int j = 0; j < spanY; j++) {
|
||||
if (mOccupied[x + i][y + j]) {
|
||||
// small optimization: we can skip to below the row we just found
|
||||
// an occupied cell
|
||||
y += j;
|
||||
continue inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cellXY != null) {
|
||||
cellXY[0] = x;
|
||||
cellXY[1] = y;
|
||||
}
|
||||
if (ignoreView != null) {
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (intersectX == -1 && intersectY == -1) {
|
||||
break;
|
||||
} else {
|
||||
// if we failed to find anything, try again but without any requirements of
|
||||
// intersecting
|
||||
intersectX = -1;
|
||||
intersectY = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreView != null) {
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when drag has left this CellLayout or has been completed (successfully or not)
|
||||
*/
|
||||
void onDragExit() {
|
||||
// Invalidate the drag data
|
||||
mDragCell[0] = -1;
|
||||
mDragCell[1] = -1;
|
||||
@@ -803,14 +885,14 @@ public class CellLayout extends ViewGroup {
|
||||
mDragRect.setEmpty();
|
||||
child.requestLayout();
|
||||
}
|
||||
onDragComplete();
|
||||
onDragExit();
|
||||
}
|
||||
|
||||
void onDropAborted(View child) {
|
||||
if (child != null) {
|
||||
((LayoutParams) child.getLayoutParams()).isDragging = false;
|
||||
}
|
||||
onDragComplete();
|
||||
onDragExit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -889,13 +971,8 @@ public class CellLayout extends ViewGroup {
|
||||
* @return True if a vacant cell was found
|
||||
*/
|
||||
public boolean getVacantCell(int[] vacant, int spanX, int spanY) {
|
||||
final int xCount = mCountX;
|
||||
final int yCount = mCountY;
|
||||
final boolean[][] occupied = mOccupied;
|
||||
|
||||
findOccupiedCells(xCount, yCount, occupied, null, true);
|
||||
|
||||
return findVacantCell(vacant, spanX, spanY, xCount, yCount, occupied);
|
||||
return findVacantCell(vacant, spanX, spanY, mCountX, mCountY, mOccupied);
|
||||
}
|
||||
|
||||
static boolean findVacantCell(int[] vacant, int spanX, int spanY,
|
||||
@@ -930,8 +1007,6 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
final int yCount = mCountY;
|
||||
final boolean[][] occupied = mOccupied;
|
||||
|
||||
findOccupiedCells(xCount, yCount, occupied, null, true);
|
||||
|
||||
final boolean[] flat = new boolean[xCount * yCount];
|
||||
for (int y = 0; y < yCount; y++) {
|
||||
for (int x = 0; x < xCount; x++) {
|
||||
@@ -942,32 +1017,34 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
return flat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the array of occupied cells.
|
||||
* @param ignoreView If non-null, the space occupied by this View is treated as vacant
|
||||
* @param ignoreFolders If true, a cell occupied by a Folder is treated as vacant
|
||||
*/
|
||||
private void findOccupiedCells(
|
||||
int xCount, int yCount, boolean[][] occupied, View ignoreView, boolean ignoreFolders) {
|
||||
|
||||
for (int x = 0; x < xCount; x++) {
|
||||
for (int y = 0; y < yCount; y++) {
|
||||
occupied[x][y] = false;
|
||||
private void clearOccupiedCells() {
|
||||
for (int x = 0; x < mCountX; x++) {
|
||||
for (int y = 0; y < mCountY; y++) {
|
||||
mOccupied[x][y] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
if ((ignoreFolders && child instanceof Folder) || child.equals(ignoreView)) {
|
||||
continue;
|
||||
}
|
||||
LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
public void onMove(View view, int newCellX, int newCellY) {
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
markCellsAsUnoccupiedForView(view);
|
||||
markCellsForView(newCellX, newCellY, lp.cellHSpan, lp.cellVSpan, true);
|
||||
}
|
||||
|
||||
for (int x = lp.cellX; x < lp.cellX + lp.cellHSpan && x < xCount; x++) {
|
||||
for (int y = lp.cellY; y < lp.cellY + lp.cellVSpan && y < yCount; y++) {
|
||||
occupied[x][y] = true;
|
||||
}
|
||||
private void markCellsAsOccupiedForView(View view) {
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
|
||||
}
|
||||
|
||||
private void markCellsAsUnoccupiedForView(View view) {
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
|
||||
}
|
||||
|
||||
private void markCellsForView(int cellX, int cellY, int spanX, int spanY, boolean value) {
|
||||
for (int x = cellX; x < cellX + spanX && x < mCountX; x++) {
|
||||
for (int y = cellY; y < cellY + spanY && y < mCountY; y++) {
|
||||
mOccupied[x][y] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1087,117 +1164,25 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
// This class stores info for two purposes:
|
||||
// 1. When dragging items (mDragInfo in Workspace), we store the View, its cellX & cellY,
|
||||
// its spanX, spanY, and the screen it is on
|
||||
// 2. When long clicking on an empty cell in a CellLayout, we save information about the
|
||||
// cellX and cellY coordinates and which page was clicked. We then set this as a tag on
|
||||
// the CellLayout that was long clicked
|
||||
static final class CellInfo implements ContextMenu.ContextMenuInfo {
|
||||
private boolean[][] mOccupied;
|
||||
private int mCountX;
|
||||
private int mCountY;
|
||||
View cell;
|
||||
int cellX = -1;
|
||||
int cellY = -1;
|
||||
// intersectX and intersectY constrain the results of findCellForSpan; any empty space
|
||||
// it results must include this point (unless intersectX and intersectY are -1)
|
||||
int intersectX = -1;
|
||||
int intersectY = -1;
|
||||
int spanX;
|
||||
int spanY;
|
||||
int screen;
|
||||
boolean valid;
|
||||
|
||||
void updateOccupiedCells(boolean[][] occupied, int xCount, int yCount) {
|
||||
mOccupied = occupied.clone();
|
||||
mCountX = xCount;
|
||||
mCountY = yCount;
|
||||
}
|
||||
|
||||
void updateOccupiedCells(boolean[] occupied, int xCount, int yCount) {
|
||||
if (mOccupied == null || mCountX != xCount || mCountY != yCount) {
|
||||
mOccupied = new boolean[xCount][yCount];
|
||||
}
|
||||
mCountX = xCount;
|
||||
mCountY = yCount;
|
||||
for (int y = 0; y < yCount; y++) {
|
||||
for (int x = 0; x < xCount; x++) {
|
||||
mOccupied[x][y] = occupied[y * xCount + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean existsEmptyCell() {
|
||||
return findCellForSpan(null, 1, 1);
|
||||
}
|
||||
/**
|
||||
* Finds the upper-left coordinate of the first rectangle in the grid that can
|
||||
* hold a cell of the specified dimensions. If intersectX and intersectY are not -1,
|
||||
* then this method will only return coordinates for rectangles that contain the cell
|
||||
* (intersectX, intersectY)
|
||||
*
|
||||
* @param cellXY The array that will contain the position of a vacant cell if such a cell
|
||||
* can be found.
|
||||
* @param spanX The horizontal span of the cell we want to find.
|
||||
* @param spanY The vertical span of the cell we want to find.
|
||||
*
|
||||
* @return True if a vacant cell of the specified dimension was found, false otherwise.
|
||||
*/
|
||||
boolean findCellForSpan(int[] cellXY, int spanX, int spanY) {
|
||||
// return the span represented by the CellInfo only there is no view there
|
||||
// (this.cell == null) and there is enough space
|
||||
|
||||
if (this.cell == null && this.spanX >= spanX && this.spanY >= spanY) {
|
||||
if (cellXY != null) {
|
||||
cellXY[0] = cellX;
|
||||
cellXY[1] = cellY;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int startX = 0;
|
||||
if (intersectX >= 0) {
|
||||
startX = Math.max(startX, intersectX - (spanX - 1));
|
||||
}
|
||||
int endX = mCountX - (spanX - 1);
|
||||
if (intersectX >= 0) {
|
||||
endX = Math.min(endX, intersectX + (spanX - 1));
|
||||
}
|
||||
int startY = 0;
|
||||
if (intersectY >= 0) {
|
||||
startY = Math.max(startY, intersectY - (spanY - 1));
|
||||
}
|
||||
int endY = mCountY - (spanY - 1);
|
||||
if (intersectY >= 0) {
|
||||
endY = Math.min(endY, intersectY + (spanY - 1));
|
||||
}
|
||||
|
||||
for (int x = startX; x < endX; x++) {
|
||||
inner:
|
||||
for (int y = startY; y < endY; y++) {
|
||||
for (int i = 0; i < spanX; i++) {
|
||||
for (int j = 0; j < spanY; j++) {
|
||||
if (mOccupied[x + i][y + j]) {
|
||||
// small optimization: we can skip to below the row we just found
|
||||
// an occupied cell
|
||||
y += j;
|
||||
continue inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cellXY != null) {
|
||||
cellXY[0] = x;
|
||||
cellXY[1] = y;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Cell[view=" + (cell == null ? "null" : cell.getClass())
|
||||
+ ", x=" + cellX + ", y=" + cellY + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public boolean lastDownOnOccupiedCell() {
|
||||
return mLastDownOnOccupiedCell;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import com.android.launcher.R;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
@@ -28,13 +25,12 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Region.Op;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.provider.LiveFolders;
|
||||
@@ -44,12 +40,14 @@ import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher.R;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomizePagedView extends PagedView
|
||||
implements View.OnLongClickListener, View.OnClickListener,
|
||||
@@ -354,6 +352,7 @@ public class CustomizePagedView extends PagedView
|
||||
}
|
||||
|
||||
final View animView = v;
|
||||
PendingAddItemInfo createItemInfo = new PendingAddItemInfo();
|
||||
switch (mCustomizationType) {
|
||||
case WidgetCustomization:
|
||||
// Get the icon as the drag representation
|
||||
@@ -365,58 +364,35 @@ public class CustomizePagedView extends PagedView
|
||||
icon.draw(c);
|
||||
|
||||
AppWidgetProviderInfo appWidgetInfo = (AppWidgetProviderInfo) v.getTag();
|
||||
LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(appWidgetInfo.provider);
|
||||
dragInfo.minWidth = appWidgetInfo.minWidth;
|
||||
dragInfo.minHeight = appWidgetInfo.minHeight;
|
||||
mDragController.startDrag(v, b, this, dragInfo, DragController.DRAG_ACTION_COPY, null);
|
||||
createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
|
||||
createItemInfo.componentName = appWidgetInfo.provider;
|
||||
mDragController.startDrag(v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY, null);
|
||||
|
||||
// Cleanup the icon
|
||||
b.recycle();
|
||||
return true;
|
||||
case FolderCustomization:
|
||||
// animate some feedback to the long press
|
||||
animateClickFeedback(v, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// add the folder
|
||||
ResolveInfo resolveInfo = (ResolveInfo) animView.getTag();
|
||||
Intent createFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
|
||||
if (resolveInfo.labelRes == R.string.group_folder) {
|
||||
// Create app shortcuts is a special built-in case of shortcuts
|
||||
createFolderIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,
|
||||
getContext().getString(R.string.group_folder));
|
||||
} else {
|
||||
ComponentName name = new ComponentName(resolveInfo.activityInfo.packageName,
|
||||
resolveInfo.activityInfo.name);
|
||||
createFolderIntent.setComponent(name);
|
||||
}
|
||||
mLauncher.prepareAddItemFromHomeCustomizationDrawer();
|
||||
mLauncher.addLiveFolder(createFolderIntent);
|
||||
}
|
||||
});
|
||||
ResolveInfo resolveInfo = (ResolveInfo) animView.getTag();
|
||||
if (resolveInfo.labelRes == R.string.group_folder) {
|
||||
UserFolderInfo folderInfo = new UserFolderInfo();
|
||||
folderInfo.title = getResources().getText(R.string.folder_name);
|
||||
mDragController.startDrag(
|
||||
v, this, folderInfo, DragController.DRAG_ACTION_COPY, null);
|
||||
} else {
|
||||
createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER;
|
||||
createItemInfo.componentName = new ComponentName(
|
||||
resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
|
||||
mDragController.startDrag(
|
||||
v, this, createItemInfo, DragController.DRAG_ACTION_COPY, null);
|
||||
}
|
||||
return true;
|
||||
case ShortcutCustomization:
|
||||
// animate some feedback to the long press
|
||||
animateClickFeedback(v, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// add the shortcut
|
||||
ResolveInfo info = (ResolveInfo) animView.getTag();
|
||||
Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
|
||||
if (info.labelRes == R.string.group_applications) {
|
||||
// Create app shortcuts is a special built-in case of shortcuts
|
||||
createShortcutIntent.putExtra(
|
||||
Intent.EXTRA_SHORTCUT_NAME,getContext().getString(
|
||||
R.string.group_applications));
|
||||
} else {
|
||||
ComponentName name = new ComponentName(info.activityInfo.packageName,
|
||||
info.activityInfo.name);
|
||||
createShortcutIntent.setComponent(name);
|
||||
}
|
||||
mLauncher.prepareAddItemFromHomeCustomizationDrawer();
|
||||
mLauncher.processShortcut(createShortcutIntent);
|
||||
}
|
||||
});
|
||||
ResolveInfo info = (ResolveInfo) animView.getTag();
|
||||
createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
|
||||
createItemInfo.componentName = new ComponentName(
|
||||
info.activityInfo.packageName, info.activityInfo.name);
|
||||
mDragController.startDrag(
|
||||
v, this, createItemInfo, DragController.DRAG_ACTION_COPY, null);
|
||||
return true;
|
||||
case ApplicationCustomization:
|
||||
// Pick up the application for dropping
|
||||
|
||||
@@ -190,6 +190,10 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDropEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createAnimations() {
|
||||
if (mInAnimation == null) {
|
||||
mInAnimation = new FastAnimationSet();
|
||||
|
||||
@@ -18,16 +18,17 @@ package com.android.launcher2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.IBinder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Vibrator;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
@@ -568,6 +569,9 @@ public class DragController {
|
||||
final int count = dropTargets.size();
|
||||
for (int i=count-1; i>=0; i--) {
|
||||
DropTarget target = dropTargets.get(i);
|
||||
if (!target.isDropEnabled())
|
||||
continue;
|
||||
|
||||
target.getHitRect(r);
|
||||
|
||||
// Convert the hit rect to screen coordinates
|
||||
|
||||
@@ -76,8 +76,7 @@ public class DragView extends View implements TweenCallback {
|
||||
scale.setScale(scaleFactor, scaleFactor);
|
||||
|
||||
mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
|
||||
mDragRegionWidth = width;
|
||||
mDragRegionHeight = height;
|
||||
setDragRegion(0, 0, width, height);
|
||||
|
||||
// The point in our scaled bitmap that the touch events are located
|
||||
mRegistrationX = registrationX + (DRAG_SCALE / 2);
|
||||
@@ -91,6 +90,22 @@ public class DragView extends View implements TweenCallback {
|
||||
mDragRegionHeight = height;
|
||||
}
|
||||
|
||||
public int getScaledDragRegionXOffset() {
|
||||
return -(int)((mScale - 1.0f) * mDragRegionWidth / 2);
|
||||
}
|
||||
|
||||
public int getScaledDragRegionWidth() {
|
||||
return (int)(mScale * mDragRegionWidth);
|
||||
}
|
||||
|
||||
public int getScaledDragRegionYOffset() {
|
||||
return -(int)((mScale - 1.0f) * mDragRegionHeight / 2);
|
||||
}
|
||||
|
||||
public int getScaledDragRegionHeight() {
|
||||
return (int)(mScale * mDragRegionWidth);
|
||||
}
|
||||
|
||||
public int getDragRegionLeft() {
|
||||
return mDragRegionLeft;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,12 @@ import android.graphics.Rect;
|
||||
*
|
||||
*/
|
||||
public interface DropTarget {
|
||||
/**
|
||||
* Used to temporarily disable certain drop targets
|
||||
*
|
||||
* @return boolean specifying whether this drop target is currently enabled
|
||||
*/
|
||||
boolean isDropEnabled();
|
||||
|
||||
/**
|
||||
* Handle an object being dropped on the DropTarget
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.android.launcher.R;
|
||||
/**
|
||||
* An icon that can appear on in the workspace representing an {@link UserFolder}.
|
||||
*/
|
||||
public class FolderIcon extends BubbleTextView implements DropTarget {
|
||||
public class FolderIcon extends DimmableBubbleTextView implements DropTarget {
|
||||
private UserFolderInfo mInfo;
|
||||
private Launcher mLauncher;
|
||||
private Drawable mCloseIcon;
|
||||
@@ -43,6 +43,10 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public boolean isDropEnabled() {
|
||||
return !((Workspace)getParent().getParent()).isSmall();
|
||||
}
|
||||
|
||||
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
|
||||
UserFolderInfo folderInfo) {
|
||||
|
||||
|
||||
@@ -50,11 +50,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
|
||||
if (findEmptyCell(context, mCoordinates, screen)) {
|
||||
CellLayout.CellInfo cell = new CellLayout.CellInfo();
|
||||
cell.cellX = mCoordinates[0];
|
||||
cell.cellY = mCoordinates[1];
|
||||
cell.screen = screen;
|
||||
|
||||
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
|
||||
|
||||
if (intent.getAction() == null) {
|
||||
@@ -66,7 +61,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
|
||||
if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
|
||||
((LauncherApplication)context.getApplicationContext()).getModel()
|
||||
.addShortcut(context, data, cell, true);
|
||||
.addShortcut(context, data, screen, mCoordinates[0], mCoordinates[1], true);
|
||||
Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
|
||||
@@ -118,8 +118,6 @@ public final class Launcher extends Activity
|
||||
static final boolean DEBUG_WIDGETS = false;
|
||||
static final boolean DEBUG_USER_INTERFACE = false;
|
||||
|
||||
private static final int WALLPAPER_SCREENS_SPAN = 2;
|
||||
|
||||
private static final int MENU_GROUP_ADD = 1;
|
||||
private static final int MENU_GROUP_WALLPAPER = MENU_GROUP_ADD + 1;
|
||||
|
||||
@@ -160,16 +158,6 @@ public final class Launcher extends Activity
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cellX";
|
||||
// Type: int
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_CELL_Y = "launcher.add_cellY";
|
||||
// Type: int
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_SPAN_X = "launcher.add_spanX";
|
||||
// Type: int
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_spanY";
|
||||
// Type: int
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_COUNT_X = "launcher.add_countX";
|
||||
// Type: int
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_COUNT_Y = "launcher.add_countY";
|
||||
// Type: int[]
|
||||
private static final String RUNTIME_STATE_PENDING_ADD_OCCUPIED_CELLS = "launcher.add_occupied_cells";
|
||||
// Type: boolean
|
||||
private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME = "launcher.rename_folder";
|
||||
// Type: long
|
||||
@@ -204,10 +192,12 @@ public final class Launcher extends Activity
|
||||
private AppWidgetManager mAppWidgetManager;
|
||||
private LauncherAppWidgetHost mAppWidgetHost;
|
||||
|
||||
private CellLayout.CellInfo mAddItemCellInfo;
|
||||
private int[] mAddItemCoordinates;
|
||||
private CellLayout.CellInfo mMenuAddInfo;
|
||||
private final int[] mCellCoordinates = new int[2];
|
||||
private int mAddScreen = -1;
|
||||
private int mAddIntersectCellX = -1;
|
||||
private int mAddIntersectCellY = -1;
|
||||
private int[] mAddDropPosition;
|
||||
private int[] mTmpAddItemCellCoordinates = new int[2];
|
||||
|
||||
private FolderInfo mFolderInfo;
|
||||
|
||||
private DeleteZone mDeleteZone;
|
||||
@@ -662,29 +652,29 @@ public final class Launcher extends Activity
|
||||
// For example, the user would PICK_SHORTCUT for "Music playlist", and we
|
||||
// launch over to the Music app to actually CREATE_SHORTCUT.
|
||||
|
||||
if (resultCode == RESULT_OK && mAddItemCellInfo != null) {
|
||||
if (resultCode == RESULT_OK && mAddScreen != -1) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_PICK_APPLICATION:
|
||||
completeAddApplication(this, data, mAddItemCellInfo);
|
||||
completeAddApplication(this, data, mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
|
||||
break;
|
||||
case REQUEST_PICK_SHORTCUT:
|
||||
processShortcut(data);
|
||||
break;
|
||||
case REQUEST_CREATE_SHORTCUT:
|
||||
completeAddShortcut(data, mAddItemCellInfo);
|
||||
completeAddShortcut(data, mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
|
||||
break;
|
||||
case REQUEST_PICK_LIVE_FOLDER:
|
||||
addLiveFolder(data);
|
||||
break;
|
||||
case REQUEST_CREATE_LIVE_FOLDER:
|
||||
completeAddLiveFolder(data, mAddItemCellInfo);
|
||||
completeAddLiveFolder(data, mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
|
||||
break;
|
||||
case REQUEST_PICK_APPWIDGET:
|
||||
addAppWidgetFromPick(data);
|
||||
break;
|
||||
case REQUEST_CREATE_APPWIDGET:
|
||||
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
|
||||
completeAddAppWidget(appWidgetId, mAddItemCellInfo);
|
||||
completeAddAppWidget(appWidgetId, mAddScreen);
|
||||
break;
|
||||
case REQUEST_PICK_WALLPAPER:
|
||||
// We just wanted the activity result here so we can clear mWaitingForResult
|
||||
@@ -821,20 +811,11 @@ public final class Launcher extends Activity
|
||||
}
|
||||
|
||||
final int addScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
|
||||
|
||||
if (addScreen > -1) {
|
||||
mAddItemCoordinates = null;
|
||||
mAddItemCellInfo = new CellLayout.CellInfo();
|
||||
final CellLayout.CellInfo addItemCellInfo = mAddItemCellInfo;
|
||||
addItemCellInfo.valid = true;
|
||||
addItemCellInfo.screen = addScreen;
|
||||
addItemCellInfo.cellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
|
||||
addItemCellInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
|
||||
addItemCellInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X);
|
||||
addItemCellInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y);
|
||||
addItemCellInfo.updateOccupiedCells(
|
||||
savedState.getBooleanArray(RUNTIME_STATE_PENDING_ADD_OCCUPIED_CELLS),
|
||||
savedState.getInt(RUNTIME_STATE_PENDING_ADD_COUNT_X),
|
||||
savedState.getInt(RUNTIME_STATE_PENDING_ADD_COUNT_Y));
|
||||
mAddScreen = addScreen;
|
||||
mAddIntersectCellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
|
||||
mAddIntersectCellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
|
||||
mRestoring = true;
|
||||
}
|
||||
|
||||
@@ -1021,9 +1002,15 @@ public final class Launcher extends Activity
|
||||
* @param data The intent describing the application.
|
||||
* @param cellInfo The position on screen where to create the shortcut.
|
||||
*/
|
||||
void completeAddApplication(Context context, Intent data, CellLayout.CellInfo cellInfo) {
|
||||
cellInfo.screen = mWorkspace.getCurrentPage();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
void completeAddApplication(Context context, Intent data, int screen,
|
||||
int intersectCellX, int intersectCellY) {
|
||||
final int[] cellXY = mTmpAddItemCellCoordinates;
|
||||
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
|
||||
|
||||
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
|
||||
showOutOfSpaceMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
final ShortcutInfo info = mModel.getShortcutInfo(context.getPackageManager(),
|
||||
data, context);
|
||||
@@ -1032,7 +1019,8 @@ public final class Launcher extends Activity
|
||||
info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
|
||||
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
||||
info.container = ItemInfo.NO_ID;
|
||||
mWorkspace.addApplicationShortcut(info, cellInfo, isWorkspaceLocked());
|
||||
mWorkspace.addApplicationShortcut(info, screen, cellXY[0], cellXY[1],
|
||||
isWorkspaceLocked(), mAddIntersectCellX, mAddIntersectCellY);
|
||||
} else {
|
||||
Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
|
||||
}
|
||||
@@ -1044,16 +1032,22 @@ public final class Launcher extends Activity
|
||||
* @param data The intent describing the shortcut.
|
||||
* @param cellInfo The position on screen where to create the shortcut.
|
||||
*/
|
||||
private void completeAddShortcut(Intent data, CellLayout.CellInfo cellInfo) {
|
||||
cellInfo.screen = mWorkspace.getCurrentPage();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
private void completeAddShortcut(Intent data, int screen,
|
||||
int intersectCellX, int intersectCellY) {
|
||||
final int[] cellXY = mTmpAddItemCellCoordinates;
|
||||
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
|
||||
|
||||
final ShortcutInfo info = mModel.addShortcut(this, data, cellInfo, false);
|
||||
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
|
||||
showOutOfSpaceMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
final ShortcutInfo info = mModel.addShortcut(
|
||||
this, data, screen, cellXY[0], cellXY[1], false);
|
||||
|
||||
if (!mRestoring) {
|
||||
final View view = createShortcut(info);
|
||||
mWorkspace.addInCurrentScreen(view, cellInfo.cellX, cellInfo.cellY, 1, 1,
|
||||
isWorkspaceLocked());
|
||||
mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1064,46 +1058,58 @@ public final class Launcher extends Activity
|
||||
* @param appWidgetId The app widget id
|
||||
* @param cellInfo The position on screen where to create the widget.
|
||||
*/
|
||||
private void completeAddAppWidget(int appWidgetId, CellLayout.CellInfo cellInfo) {
|
||||
private void completeAddAppWidget(int appWidgetId, int screen) {
|
||||
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
|
||||
|
||||
// Calculate the grid spans needed to fit this widget
|
||||
CellLayout layout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen);
|
||||
int[] spans = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight, null);
|
||||
CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
|
||||
int[] spanXY = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight, null);
|
||||
|
||||
// Try finding open space on Launcher screen
|
||||
// We have saved the position to which the widget was dragged-- this really only matters
|
||||
// if we are placing widgets on a "spring-loaded" screen
|
||||
final int[] xy = mCellCoordinates;
|
||||
final int[] cellXY = mTmpAddItemCellCoordinates;
|
||||
|
||||
// For now, we don't save the coordinate where we dropped the icon because we're not
|
||||
// supporting spring-loaded mini-screens; however, leaving the ability to directly place
|
||||
// a widget on the home screen in case we want to add it in the future
|
||||
final int[] xyTouch = null;
|
||||
//final int[] xyTouch = mAddItemCoordinates;
|
||||
final int[] touchXY = null;
|
||||
//final int[] touchXY = mAddDropPosition;
|
||||
boolean findNearestVacantAreaFailed = false;
|
||||
if (xyTouch != null) {
|
||||
CellLayout screen = (CellLayout) mWorkspace.getChildAt(cellInfo.screen);
|
||||
int[] result = screen.findNearestVacantArea(
|
||||
mAddItemCoordinates[0], mAddItemCoordinates[1],
|
||||
spans[0], spans[1], cellInfo, xy);
|
||||
boolean foundCellSpan = false;
|
||||
if (touchXY != null) {
|
||||
// when dragging and dropping, just find the closest free spot
|
||||
CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
|
||||
int[] result = screenLayout.findNearestVacantArea(
|
||||
touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
|
||||
findNearestVacantAreaFailed = (result == null);
|
||||
foundCellSpan = !findNearestVacantAreaFailed;
|
||||
} else {
|
||||
if (mAddIntersectCellX != -1 && mAddIntersectCellY != -1) {
|
||||
// if we long pressed on an empty cell to bring up a menu,
|
||||
// make sure we intersect the empty cell
|
||||
foundCellSpan = layout.findCellForSpanThatIntersects(cellXY, spanXY[0], spanXY[1],
|
||||
mAddIntersectCellX, mAddIntersectCellY);
|
||||
} else {
|
||||
// if we went through the menu -> add, just find any spot
|
||||
foundCellSpan = layout.findCellForSpan(cellXY, spanXY[0], spanXY[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (findNearestVacantAreaFailed ||
|
||||
(xyTouch == null && !findSlot(cellInfo, xy, spans[0], spans[1]))) {
|
||||
if (!foundCellSpan) {
|
||||
if (appWidgetId != -1) mAppWidgetHost.deleteAppWidgetId(appWidgetId);
|
||||
showOutOfSpaceMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
// Build Launcher-specific widget info and save to database
|
||||
LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId);
|
||||
launcherInfo.spanX = spans[0];
|
||||
launcherInfo.spanY = spans[1];
|
||||
launcherInfo.spanX = spanXY[0];
|
||||
launcherInfo.spanY = spanXY[1];
|
||||
|
||||
LauncherModel.addItemToDatabase(this, launcherInfo,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
cellInfo.screen, xy[0], xy[1], false);
|
||||
screen, cellXY[0], cellXY[1], false);
|
||||
|
||||
if (!mRestoring) {
|
||||
mDesktopItems.add(launcherInfo);
|
||||
@@ -1114,11 +1120,15 @@ public final class Launcher extends Activity
|
||||
launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);
|
||||
launcherInfo.hostView.setTag(launcherInfo);
|
||||
|
||||
mWorkspace.addInScreen(launcherInfo.hostView, cellInfo.screen, xy[0], xy[1],
|
||||
mWorkspace.addInScreen(launcherInfo.hostView, screen, cellXY[0], cellXY[1],
|
||||
launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
|
||||
}
|
||||
}
|
||||
|
||||
void showOutOfSpaceMessage() {
|
||||
Toast.makeText(this, getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public void removeAppWidget(LauncherAppWidgetInfo launcherInfo) {
|
||||
mDesktopItems.remove(launcherInfo);
|
||||
launcherInfo.hostView = null;
|
||||
@@ -1219,19 +1229,10 @@ public final class Launcher extends Activity
|
||||
outState.putBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, true);
|
||||
}
|
||||
|
||||
if (mAddItemCellInfo != null && mAddItemCellInfo.valid && mWaitingForResult) {
|
||||
final CellLayout.CellInfo addItemCellInfo = mAddItemCellInfo;
|
||||
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(addItemCellInfo.screen);
|
||||
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, addItemCellInfo.screen);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, addItemCellInfo.cellX);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, addItemCellInfo.cellY);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, addItemCellInfo.spanX);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y, addItemCellInfo.spanY);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_COUNT_X, layout.getCountX());
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_COUNT_Y, layout.getCountY());
|
||||
outState.putBooleanArray(RUNTIME_STATE_PENDING_ADD_OCCUPIED_CELLS,
|
||||
layout.getOccupiedCellsFlattened());
|
||||
if (mAddScreen > -1 && mWaitingForResult) {
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mAddScreen);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mAddIntersectCellX);
|
||||
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mAddIntersectCellY);
|
||||
}
|
||||
|
||||
if (mFolderInfo != null && mWaitingForResult) {
|
||||
@@ -1353,20 +1354,13 @@ public final class Launcher extends Activity
|
||||
|
||||
// Disable add if the workspace is full.
|
||||
if (visible) {
|
||||
mMenuAddInfo = mWorkspace.updateOccupiedCellsForCurrentScreen(null);
|
||||
menu.setGroupEnabled(MENU_GROUP_ADD, mMenuAddInfo != null && mMenuAddInfo.valid);
|
||||
CellLayout layout = (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
|
||||
menu.setGroupEnabled(MENU_GROUP_ADD, layout.existsEmptyCell());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// we need to initialize mAddItemCellInfo before adding something to the homescreen -- when
|
||||
// using the settings menu to add an item, something similar happens in showAddDialog
|
||||
public void prepareAddItemFromHomeCustomizationDrawer() {
|
||||
mMenuAddInfo = mWorkspace.updateOccupiedCellsForCurrentScreen(null);
|
||||
mAddItemCellInfo = mMenuAddInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
@@ -1410,16 +1404,24 @@ public final class Launcher extends Activity
|
||||
}
|
||||
} else {
|
||||
closeAllApps(true);
|
||||
showAddDialog(mMenuAddInfo);
|
||||
showAddDialog(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void addAppWidgetFromDrop(ComponentName appWidgetProvider, CellLayout.CellInfo cellInfo,
|
||||
int[] position) {
|
||||
mAddItemCellInfo = cellInfo;
|
||||
private void resetAddInfo() {
|
||||
mAddScreen = -1;
|
||||
mAddIntersectCellX = -1;
|
||||
mAddIntersectCellY = -1;
|
||||
mAddDropPosition = null;
|
||||
}
|
||||
|
||||
void addAppWidgetFromDrop(ComponentName appWidgetProvider, int screen, int[] position) {
|
||||
resetAddInfo();
|
||||
mAddScreen = screen;
|
||||
|
||||
// only set mAddDropPosition if we dropped on home screen in "spring-loaded" manner
|
||||
mAddDropPosition = position;
|
||||
|
||||
// only set mAddItemCoordinates if we dropped on home screen in "spring-loaded" manner
|
||||
mAddItemCoordinates = position;
|
||||
int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
|
||||
AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, appWidgetProvider);
|
||||
addAppWidgetImpl(appWidgetId);
|
||||
@@ -1445,10 +1447,20 @@ public final class Launcher extends Activity
|
||||
startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
|
||||
} else {
|
||||
// Otherwise just add it
|
||||
completeAddAppWidget(appWidgetId, mAddItemCellInfo);
|
||||
completeAddAppWidget(appWidgetId, mAddScreen);
|
||||
}
|
||||
}
|
||||
|
||||
void processShortcutFromDrop(ComponentName componentName, int screen, int[] position) {
|
||||
resetAddInfo();
|
||||
mAddScreen = screen;
|
||||
mAddDropPosition = position;
|
||||
|
||||
Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
|
||||
createShortcutIntent.setComponent(componentName);
|
||||
processShortcut(createShortcutIntent);
|
||||
}
|
||||
|
||||
void processShortcut(Intent intent) {
|
||||
// Handle case where user selected "Applications"
|
||||
String applicationName = getResources().getString(R.string.group_applications);
|
||||
@@ -1470,59 +1482,75 @@ public final class Launcher extends Activity
|
||||
startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
|
||||
}
|
||||
|
||||
void addLiveFolder(Intent intent) {
|
||||
void addLiveFolderFromDrop(ComponentName componentName, int screen, int[] position) {
|
||||
resetAddInfo();
|
||||
mAddScreen = screen;
|
||||
mAddDropPosition = position;
|
||||
|
||||
Intent createFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
|
||||
createFolderIntent.setComponent(componentName);
|
||||
|
||||
addLiveFolder(createFolderIntent);
|
||||
}
|
||||
|
||||
void addLiveFolder(Intent intent) { // YYY add screen intersect etc. parameters here
|
||||
// Handle case where user selected "Folder"
|
||||
String folderName = getResources().getString(R.string.group_folder);
|
||||
String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
|
||||
if (folderName != null && folderName.equals(shortcutName)) {
|
||||
addFolder();
|
||||
addFolder(mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
|
||||
} else {
|
||||
startActivityForResult(intent, REQUEST_CREATE_LIVE_FOLDER);
|
||||
}
|
||||
}
|
||||
|
||||
void addFolder() {
|
||||
void addFolder(int screen, int intersectCellX, int intersectCellY) {
|
||||
UserFolderInfo folderInfo = new UserFolderInfo();
|
||||
folderInfo.title = getText(R.string.folder_name);
|
||||
|
||||
CellLayout.CellInfo cellInfo = mAddItemCellInfo;
|
||||
cellInfo.screen = mWorkspace.getCurrentPage();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
|
||||
final int[] cellXY = mTmpAddItemCellCoordinates;
|
||||
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
|
||||
showOutOfSpaceMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the model
|
||||
LauncherModel.addItemToDatabase(this, folderInfo,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
mWorkspace.getCurrentPage(), cellInfo.cellX, cellInfo.cellY, false);
|
||||
screen, cellXY[0], cellXY[1], false);
|
||||
sFolders.put(folderInfo.id, folderInfo);
|
||||
|
||||
// Create the view
|
||||
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
|
||||
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), folderInfo);
|
||||
mWorkspace.addInCurrentScreen(newFolder,
|
||||
cellInfo.cellX, cellInfo.cellY, 1, 1, isWorkspaceLocked());
|
||||
mWorkspace.addInScreen(newFolder, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
|
||||
}
|
||||
|
||||
void removeFolder(FolderInfo folder) {
|
||||
sFolders.remove(folder.id);
|
||||
}
|
||||
|
||||
private void completeAddLiveFolder(Intent data, CellLayout.CellInfo cellInfo) {
|
||||
cellInfo.screen = mWorkspace.getCurrentPage();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
private void completeAddLiveFolder(Intent data, int screen, int intersectCellX, int intersectCellY) {
|
||||
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
|
||||
final int[] cellXY = mTmpAddItemCellCoordinates;
|
||||
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
|
||||
showOutOfSpaceMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
final LiveFolderInfo info = addLiveFolder(this, data, cellInfo, false);
|
||||
final LiveFolderInfo info = addLiveFolder(this, data, screen, cellXY[0], cellXY[1], false);
|
||||
|
||||
if (!mRestoring) {
|
||||
final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this,
|
||||
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
|
||||
mWorkspace.addInCurrentScreen(view, cellInfo.cellX, cellInfo.cellY, 1, 1,
|
||||
isWorkspaceLocked());
|
||||
mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
|
||||
}
|
||||
}
|
||||
|
||||
static LiveFolderInfo addLiveFolder(Context context, Intent data,
|
||||
CellLayout.CellInfo cellInfo, boolean notify) {
|
||||
int screen, int cellX, int cellY, boolean notify) {
|
||||
|
||||
Intent baseIntent = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT);
|
||||
String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
|
||||
@@ -1558,34 +1586,12 @@ public final class Launcher extends Activity
|
||||
LiveFolders.DISPLAY_MODE_GRID);
|
||||
|
||||
LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
|
||||
screen, cellX, cellY, notify);
|
||||
sFolders.put(info.id, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private boolean findSingleSlot(CellLayout.CellInfo cellInfo) {
|
||||
final int[] xy = new int[2];
|
||||
if (findSlot(cellInfo, xy, 1, 1)) {
|
||||
cellInfo.cellX = xy[0];
|
||||
cellInfo.cellY = xy[1];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean findSlot(CellLayout.CellInfo cellInfo, int[] xy, int spanX, int spanY) {
|
||||
if (!cellInfo.findCellForSpan(xy, spanX, spanY)) {
|
||||
CellLayout targetLayout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen);
|
||||
cellInfo = targetLayout.updateOccupiedCells(null, null);
|
||||
if (!cellInfo.findCellForSpan(xy, spanX, spanY)) {
|
||||
Toast.makeText(this, getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showNotifications() {
|
||||
final StatusBarManager statusBar = (StatusBarManager) getSystemService(STATUS_BAR_SERVICE);
|
||||
if (statusBar != null) {
|
||||
@@ -1907,28 +1913,38 @@ public final class Launcher extends Activity
|
||||
v = (View) v.getParent();
|
||||
}
|
||||
|
||||
CellLayout.CellInfo cellInfo = (CellLayout.CellInfo) v.getTag();
|
||||
|
||||
resetAddInfo();
|
||||
CellLayout.CellInfo longClickCellInfo = (CellLayout.CellInfo) v.getTag();
|
||||
// This happens when long clicking an item with the dpad/trackball
|
||||
if (cellInfo == null) {
|
||||
if (longClickCellInfo == null || !longClickCellInfo.valid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final View itemUnderLongClick = longClickCellInfo.cell;
|
||||
|
||||
if (mWorkspace.allowLongPress()) {
|
||||
if (cellInfo.cell == null) {
|
||||
if (cellInfo.valid) {
|
||||
// User long pressed on empty space
|
||||
mWorkspace.setAllowLongPress(false);
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
showAddDialog(cellInfo);
|
||||
if (itemUnderLongClick == null) {
|
||||
// User long pressed on empty space
|
||||
mWorkspace.setAllowLongPress(false);
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
// Animate the widget chooser up from the bottom of the screen
|
||||
if (!isCustomizationDrawerVisible()) {
|
||||
showCustomizationDrawer(true);
|
||||
}
|
||||
} else {
|
||||
showAddDialog(longClickCellInfo.cellX, longClickCellInfo.cellY);
|
||||
}
|
||||
} else {
|
||||
if (!(cellInfo.cell instanceof Folder)) {
|
||||
if (!(itemUnderLongClick instanceof Folder)) {
|
||||
// User long pressed on an item
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
mWorkspace.startDrag(cellInfo);
|
||||
mAddIntersectCellX = longClickCellInfo.cellX;
|
||||
mAddIntersectCellY = longClickCellInfo.cellY;
|
||||
mWorkspace.startDrag(longClickCellInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2106,9 +2122,11 @@ public final class Launcher extends Activity
|
||||
showDialog(DIALOG_RENAME_FOLDER);
|
||||
}
|
||||
|
||||
private void showAddDialog(CellLayout.CellInfo cellInfo) {
|
||||
mAddItemCellInfo = cellInfo;
|
||||
mAddItemCoordinates = null;
|
||||
private void showAddDialog(int intersectX, int intersectY) {
|
||||
resetAddInfo();
|
||||
mAddIntersectCellX = intersectX;
|
||||
mAddIntersectCellY = intersectY;
|
||||
mAddScreen = mWorkspace.getCurrentPage();
|
||||
mWaitingForResult = true;
|
||||
showDialog(DIALOG_CREATE_SHORTCUT);
|
||||
}
|
||||
@@ -2634,7 +2652,7 @@ public final class Launcher extends Activity
|
||||
mAllAppsPagedView.endChoiceMode();
|
||||
mCustomizePagedView.endChoiceMode();
|
||||
} else {
|
||||
Toast.makeText(this, getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
|
||||
showOutOfSpaceMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1478,11 +1478,11 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
ShortcutInfo addShortcut(Context context, Intent data,
|
||||
CellLayout.CellInfo cellInfo, boolean notify) {
|
||||
int screen, int cellX, int cellY, boolean notify) {
|
||||
|
||||
final ShortcutInfo info = infoFromShortcutIntent(context, data);
|
||||
addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
|
||||
screen, cellX, cellY, notify);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -28,6 +29,8 @@ class LiveFolderInfo extends FolderInfo {
|
||||
*/
|
||||
Intent baseIntent;
|
||||
|
||||
ComponentName componentName;
|
||||
|
||||
/**
|
||||
* The live folder's content uri.
|
||||
*/
|
||||
|
||||
@@ -334,7 +334,7 @@ public abstract class PagedView extends ViewGroup {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
|
||||
setHorizontalScrollBarEnabled(false);
|
||||
int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.ComponentName;
|
||||
|
||||
/**
|
||||
* We pass this object with a drag from the customization tray
|
||||
*/
|
||||
class PendingAddItemInfo extends ItemInfo {
|
||||
/**
|
||||
* The component that will be created.
|
||||
*/
|
||||
ComponentName componentName;
|
||||
}
|
||||
@@ -72,6 +72,10 @@ public class UserFolder extends Folder implements DropTarget {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDropEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void bind(FolderInfo info) {
|
||||
super.bind(info);
|
||||
setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import com.android.launcher.R;
|
||||
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.Animator.AnimatorListener;
|
||||
import android.app.WallpaperManager;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
@@ -46,7 +46,6 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -103,8 +102,10 @@ public class Workspace extends SmoothPagedView
|
||||
|
||||
private int[] mTempCell = new int[2];
|
||||
private int[] mTempEstimate = new int[2];
|
||||
private float[] mTempOriginXY = new float[2];
|
||||
private float[] mTempDragCoordinates = new float[2];
|
||||
private float[] mTempDragBottomRightCoordinates = new float[2];
|
||||
private Matrix mTempInverseMatrix = new Matrix();
|
||||
|
||||
private static final int DEFAULT_CELL_COUNT_X = 4;
|
||||
private static final int DEFAULT_CELL_COUNT_Y = 4;
|
||||
@@ -117,7 +118,6 @@ public class Workspace extends SmoothPagedView
|
||||
private boolean mIsSmall;
|
||||
private AnimatorListener mUnshrinkAnimationListener;
|
||||
|
||||
|
||||
/**
|
||||
* Used to inflate the Workspace from XML.
|
||||
*
|
||||
@@ -273,35 +273,6 @@ public class Workspace extends SmoothPagedView
|
||||
updateWallpaperOffset(mScrollX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified child in the current screen. The position and dimension of
|
||||
* the child are defined by x, y, spanX and spanY.
|
||||
*
|
||||
* @param child The child to add in one of the workspace's screens.
|
||||
* @param x The X position of the child in the screen's grid.
|
||||
* @param y The Y position of the child in the screen's grid.
|
||||
* @param spanX The number of cells spanned horizontally by the child.
|
||||
* @param spanY The number of cells spanned vertically by the child.
|
||||
*/
|
||||
void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) {
|
||||
addInScreen(child, mCurrentPage, x, y, spanX, spanY, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified child in the current screen. The position and dimension of
|
||||
* the child are defined by x, y, spanX and spanY.
|
||||
*
|
||||
* @param child The child to add in one of the workspace's screens.
|
||||
* @param x The X position of the child in the screen's grid.
|
||||
* @param y The Y position of the child in the screen's grid.
|
||||
* @param spanX The number of cells spanned horizontally by the child.
|
||||
* @param spanY The number of cells spanned vertically by the child.
|
||||
* @param insert When true, the child is inserted at the beginning of the children list.
|
||||
*/
|
||||
void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) {
|
||||
addInScreen(child, mCurrentPage, x, y, spanX, spanY, insert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified child in the specified screen. The position and dimension of
|
||||
* the child are defined by x, y, spanX and spanY.
|
||||
@@ -369,14 +340,6 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
}
|
||||
|
||||
CellLayout.CellInfo updateOccupiedCellsForCurrentScreen(boolean[] occupied) {
|
||||
CellLayout group = (CellLayout) getChildAt(mCurrentPage);
|
||||
if (group != null) {
|
||||
return group.updateOccupiedCells(occupied, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
// this is an intercepted event being forwarded from a cell layout
|
||||
if (mIsSmall) {
|
||||
@@ -469,7 +432,7 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
// if shrinkToBottom() is called on initialization, it has to be deferred
|
||||
@@ -776,43 +739,40 @@ public class Workspace extends SmoothPagedView
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
|
||||
addApplicationShortcut(info, cellInfo, false);
|
||||
void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
|
||||
boolean insertAtFirst, int intersectX, int intersectY) {
|
||||
final CellLayout cellLayout = (CellLayout) getChildAt(screen);
|
||||
View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
|
||||
|
||||
final int[] cellXY = new int[2];
|
||||
cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
|
||||
addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
|
||||
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
|
||||
cellXY[0], cellXY[1]);
|
||||
}
|
||||
|
||||
void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
|
||||
boolean insertAtFirst) {
|
||||
final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
|
||||
final int[] result = new int[2];
|
||||
|
||||
layout.cellToPoint(cellInfo.cellX, cellInfo.cellY, result);
|
||||
onDropExternal(result[0], result[1], info, layout, insertAtFirst);
|
||||
}
|
||||
|
||||
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
|
||||
DragView dragView, Object dragInfo) {
|
||||
CellLayout cellLayout = getCurrentDropLayout();
|
||||
CellLayout cellLayout;
|
||||
int originX = x - xOffset;
|
||||
int originY = y - yOffset;
|
||||
if (mIsSmall) {
|
||||
// find out which target layout is over
|
||||
final float[] localXY = mTempDragCoordinates;
|
||||
localXY[0] = originX;
|
||||
localXY[1] = originY;
|
||||
final float[] localBottomRightXY = mTempDragBottomRightCoordinates;
|
||||
// we need to subtract left/top here because DragController already adds
|
||||
// dragRegionLeft/Top to xOffset and yOffset
|
||||
localBottomRightXY[0] = originX + dragView.getDragRegionWidth();
|
||||
localBottomRightXY[1] = originY + dragView.getDragRegionHeight();
|
||||
cellLayout = findMatchingPageForDragOver(localXY, localBottomRightXY);
|
||||
cellLayout = findMatchingPageForDragOver(dragView, originX, originY);
|
||||
if (cellLayout == null) {
|
||||
// cancel the drag if we're not over a mini-screen at time of drop
|
||||
// TODO: maybe add a nice fade here?
|
||||
return;
|
||||
}
|
||||
// localXY will be transformed into the local screen's coordinate space; save that info
|
||||
originX = (int)localXY[0];
|
||||
originY = (int)localXY[1];
|
||||
// get originX and originY in the local coordinate system of the screen
|
||||
mTempOriginXY[0] = originX;
|
||||
mTempOriginXY[1] = originY;
|
||||
mapPointGlobalToLocal(cellLayout, mTempOriginXY);
|
||||
originX = (int)mTempOriginXY[0];
|
||||
originY = (int)mTempOriginXY[1];
|
||||
} else {
|
||||
cellLayout = getCurrentDropLayout();
|
||||
}
|
||||
if (source != this) {
|
||||
onDropExternal(originX, originY, dragInfo, cellLayout);
|
||||
@@ -835,8 +795,8 @@ public class Workspace extends SmoothPagedView
|
||||
|
||||
// update the item's position after drop
|
||||
final ItemInfo info = (ItemInfo) cell.getTag();
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell
|
||||
.getLayoutParams();
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
|
||||
cellLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
|
||||
lp.cellX = mTargetCell[0];
|
||||
lp.cellY = mTargetCell[1];
|
||||
|
||||
@@ -854,6 +814,10 @@ public class Workspace extends SmoothPagedView
|
||||
public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
|
||||
DragView dragView, Object dragInfo) {
|
||||
|
||||
if (mIsSmall) {
|
||||
// If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
|
||||
return null;
|
||||
}
|
||||
// We may need to delegate the drag to a child view. If a 1x1 item
|
||||
// would land in a cell occupied by a DragTarget (e.g. a Folder),
|
||||
// then drag events should be handled by that child.
|
||||
@@ -871,12 +835,12 @@ public class Workspace extends SmoothPagedView
|
||||
dragPointX = x;
|
||||
dragPointY = y;
|
||||
}
|
||||
dragPointX += mScrollX - currentLayout.getLeft();
|
||||
dragPointY += mScrollY - currentLayout.getTop();
|
||||
|
||||
// If we are dragging over a cell that contains a DropTarget that will
|
||||
// accept the drop, delegate to that DropTarget.
|
||||
final int[] cellXY = mTempCell;
|
||||
int localDragPointX = dragPointX - (currentLayout.getLeft() - mScrollX);
|
||||
int localDragPointY = dragPointY - (currentLayout.getTop() - mScrollY);
|
||||
currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
|
||||
View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
|
||||
if (child instanceof DropTarget) {
|
||||
@@ -888,29 +852,32 @@ public class Workspace extends SmoothPagedView
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void mapPointGlobalToLocal(View v, float[] xy) {
|
||||
xy[0] = xy[0] + mScrollX - v.getLeft();
|
||||
xy[1] = xy[1] + mScrollY - v.getTop();
|
||||
v.getMatrix().invert(mTempInverseMatrix);
|
||||
mTempInverseMatrix.mapPoints(xy);
|
||||
}
|
||||
|
||||
// xy = upper left corner of item being dragged
|
||||
// bottomRightXy = lower right corner of item being dragged
|
||||
// This method will see which mini-screen is most overlapped by the item being dragged, and
|
||||
// return it. It will also transform the parameters xy and bottomRightXy into the local
|
||||
// coordinate space of the returned screen
|
||||
private CellLayout findMatchingPageForDragOver(float[] xy, float[] bottomRightXy) {
|
||||
float x = xy[0];
|
||||
float y = xy[1];
|
||||
float right = bottomRightXy[0];
|
||||
float bottom = bottomRightXy[1];
|
||||
|
||||
float bestX = 0;
|
||||
float bestY = 0;
|
||||
float bestRight = 0;
|
||||
float bestBottom = 0;
|
||||
|
||||
Matrix inverseMatrix = new Matrix();
|
||||
private CellLayout findMatchingPageForDragOver(DragView dragView, int originX, int originY) {
|
||||
float x = originX + dragView.getScaledDragRegionXOffset();
|
||||
float y = originY + dragView.getScaledDragRegionYOffset();
|
||||
float right = x + dragView.getScaledDragRegionWidth();
|
||||
float bottom = y + dragView.getScaledDragRegionHeight();
|
||||
|
||||
// We loop through all the screens (ie CellLayouts) and see which one overlaps the most
|
||||
// with the item being dragged.
|
||||
final int screenCount = getChildCount();
|
||||
CellLayout bestMatchingScreen = null;
|
||||
float bestOverlapSoFar = 0;
|
||||
float smallestDistSoFar = Float.MAX_VALUE;
|
||||
final float[] xy = mTempDragCoordinates;
|
||||
final float[] bottomRightXy = mTempDragBottomRightCoordinates;
|
||||
for (int i = 0; i < screenCount; i++) {
|
||||
CellLayout cl = (CellLayout)getChildAt(i);
|
||||
// Transform the coordinates of the item being dragged to the CellLayout's coordinates
|
||||
@@ -918,57 +885,76 @@ public class Workspace extends SmoothPagedView
|
||||
float top = cl.getTop();
|
||||
xy[0] = x + mScrollX - left;
|
||||
xy[1] = y + mScrollY - top;
|
||||
cl.getMatrix().invert(inverseMatrix);
|
||||
|
||||
bottomRightXy[0] = right + mScrollX - left;
|
||||
bottomRightXy[1] = bottom + mScrollY - top;
|
||||
|
||||
inverseMatrix.mapPoints(xy);
|
||||
inverseMatrix.mapPoints(bottomRightXy);
|
||||
cl.getMatrix().invert(mTempInverseMatrix);
|
||||
mTempInverseMatrix.mapPoints(xy);
|
||||
mTempInverseMatrix.mapPoints(bottomRightXy);
|
||||
|
||||
float dragRegionX = xy[0];
|
||||
float dragRegionY = xy[1];
|
||||
float dragRegionRight = bottomRightXy[0];
|
||||
float dragRegionBottom = bottomRightXy[1];
|
||||
float dragRegionCenterX = (dragRegionX + dragRegionRight) / 2.0f;
|
||||
float dragRegionCenterY = (dragRegionY + dragRegionBottom) / 2.0f;
|
||||
|
||||
// Find the overlapping region
|
||||
float overlapLeft = Math.max(0f, dragRegionX);
|
||||
float overlapTop = Math.max(0f, dragRegionY);
|
||||
float overlapBottom = Math.min(cl.getHeight(), dragRegionBottom);
|
||||
float overlapRight = Math.min(cl.getWidth(), dragRegionRight);
|
||||
|
||||
if (overlapRight >= 0 && overlapLeft <= cl.getWidth() &&
|
||||
overlapTop >= 0 && overlapBottom <= cl.getHeight()) {
|
||||
// Calculate the size of the overlapping region
|
||||
(overlapTop >= 0 && overlapBottom <= cl.getHeight())) {
|
||||
// Calculate the distance between the two centers
|
||||
float distX = dragRegionCenterX - cl.getWidth()/2;
|
||||
float distY = dragRegionCenterY - cl.getHeight()/2;
|
||||
float dist = distX * distX + distY * distY;
|
||||
|
||||
float overlap = (overlapRight - overlapLeft) * (overlapBottom - overlapTop);
|
||||
if (overlap > bestOverlapSoFar) {
|
||||
bestOverlapSoFar = overlap;
|
||||
|
||||
// Calculate the closest overlapping region
|
||||
if (overlap > 0 && dist < smallestDistSoFar) {
|
||||
smallestDistSoFar = dist;
|
||||
bestMatchingScreen = cl;
|
||||
bestX = xy[0];
|
||||
bestY = xy[1];
|
||||
bestRight = bottomRightXy[0];
|
||||
bestBottom = bottomRightXy[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestMatchingScreen != null && bestMatchingScreen != mDragTargetLayout) {
|
||||
|
||||
if (bestMatchingScreen != mDragTargetLayout) {
|
||||
if (mDragTargetLayout != null) {
|
||||
mDragTargetLayout.onDragComplete();
|
||||
mDragTargetLayout.onDragExit();
|
||||
}
|
||||
mDragTargetLayout = bestMatchingScreen;
|
||||
}
|
||||
xy[0] = bestX;
|
||||
xy[1] = bestY;
|
||||
bottomRightXy[0] = bestRight;
|
||||
bottomRightXy[1] = bestBottom;
|
||||
return bestMatchingScreen;
|
||||
}
|
||||
|
||||
public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
|
||||
DragView dragView, Object dragInfo) {
|
||||
CellLayout currentLayout;
|
||||
int originX = x - xOffset;
|
||||
int originY = y - yOffset;
|
||||
if (mIsSmall) {
|
||||
currentLayout = findMatchingPageForDragOver(dragView, originX, originY);
|
||||
|
||||
if (currentLayout == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentLayout.setHover(true);
|
||||
// get originX and originY in the local coordinate system of the screen
|
||||
mTempOriginXY[0] = originX;
|
||||
mTempOriginXY[1] = originY;
|
||||
mapPointGlobalToLocal(currentLayout, mTempOriginXY);
|
||||
originX = (int)mTempOriginXY[0];
|
||||
originY = (int)mTempOriginXY[1];
|
||||
} else {
|
||||
currentLayout = getCurrentDropLayout();
|
||||
}
|
||||
|
||||
final ItemInfo item = (ItemInfo)dragInfo;
|
||||
CellLayout currentLayout = getCurrentDropLayout();
|
||||
|
||||
if (dragInfo instanceof LauncherAppWidgetInfo) {
|
||||
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
|
||||
@@ -980,25 +966,6 @@ public class Workspace extends SmoothPagedView
|
||||
item.spanY = spans[1];
|
||||
}
|
||||
}
|
||||
int originX = x - xOffset;
|
||||
int originY = y - yOffset;
|
||||
if (mIsSmall) {
|
||||
// find out which mini screen the dragged item is over
|
||||
final float[] localXY = mTempDragCoordinates;
|
||||
localXY[0] = originX;
|
||||
localXY[1] = originY;
|
||||
final float[] localBottomRightXY = mTempDragBottomRightCoordinates;
|
||||
|
||||
localBottomRightXY[0] = originX + dragView.getDragRegionWidth();
|
||||
localBottomRightXY[1] = originY + dragView.getDragRegionHeight();
|
||||
currentLayout = findMatchingPageForDragOver(localXY, localBottomRightXY);
|
||||
if (currentLayout != null) {
|
||||
currentLayout.setHover(true);
|
||||
}
|
||||
|
||||
originX = (int)localXY[0];
|
||||
originY = (int)localXY[1];
|
||||
}
|
||||
|
||||
if (source != this) {
|
||||
// This is a hack to fix the point used to determine which cell an icon from the all
|
||||
@@ -1015,7 +982,7 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
if (currentLayout != mDragTargetLayout) {
|
||||
if (mDragTargetLayout != null) {
|
||||
mDragTargetLayout.onDragComplete();
|
||||
mDragTargetLayout.onDragExit();
|
||||
}
|
||||
mDragTargetLayout = currentLayout;
|
||||
}
|
||||
@@ -1028,14 +995,14 @@ public class Workspace extends SmoothPagedView
|
||||
int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
|
||||
int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
|
||||
mDragTargetLayout.visualizeDropLocation(
|
||||
child, localOriginX, localOriginY, item.spanX, item.spanY);
|
||||
child, localOriginX, localOriginY, item.spanX, item.spanY, child);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDragExit(DragSource source, int x, int y, int xOffset,
|
||||
int yOffset, DragView dragView, Object dragInfo) {
|
||||
if (mDragTargetLayout != null) {
|
||||
mDragTargetLayout.onDragComplete();
|
||||
mDragTargetLayout.onDragExit();
|
||||
mDragTargetLayout = null;
|
||||
}
|
||||
}
|
||||
@@ -1055,17 +1022,43 @@ public class Workspace extends SmoothPagedView
|
||||
CellLayout cl = (CellLayout) layout;
|
||||
ItemInfo info = (ItemInfo) dragInfo;
|
||||
|
||||
final CellLayout.CellInfo cellInfo = cl.updateOccupiedCells(null, null);
|
||||
if (cellInfo.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
|
||||
if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
|
||||
onDropExternal(0, 0, dragInfo, cl, false);
|
||||
return true;
|
||||
}
|
||||
mLauncher.showOutOfSpaceMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Drag from somewhere else
|
||||
private void onDropExternal(int x, int y, Object dragInfo,
|
||||
CellLayout cellLayout, boolean insertAtFirst) {
|
||||
// Drag from somewhere else
|
||||
int screen = indexOfChild(cellLayout);
|
||||
if (dragInfo instanceof PendingAddItemInfo) {
|
||||
PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
|
||||
// When dragging and dropping from customization tray, we deal with creating
|
||||
// widgets/shortcuts/folders in a slightly different way
|
||||
int[] touchXY = new int[2];
|
||||
touchXY[0] = x;
|
||||
touchXY[1] = y;
|
||||
switch (info.itemType) {
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
|
||||
mLauncher.addAppWidgetFromDrop(info.componentName, screen, touchXY);
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
|
||||
mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||
mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown item type: " + info.itemType);
|
||||
}
|
||||
cellLayout.onDragExit();
|
||||
return;
|
||||
}
|
||||
|
||||
// This is for other drag/drop cases, like dragging from All Apps
|
||||
ItemInfo info = (ItemInfo) dragInfo;
|
||||
|
||||
View view = null;
|
||||
@@ -1082,25 +1075,15 @@ public class Workspace extends SmoothPagedView
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
|
||||
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
|
||||
(ViewGroup) getChildAt(mCurrentPage),
|
||||
((UserFolderInfo) info));
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
|
||||
cellLayout.setTagToCellInfoForPoint(x, y);
|
||||
int[] position = new int[2];
|
||||
position[0] = x;
|
||||
position[1] = y;
|
||||
mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName,
|
||||
cellLayout.getTag(), position);
|
||||
cellLayout, ((UserFolderInfo) info));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown item type: "
|
||||
+ info.itemType);
|
||||
throw new IllegalStateException("Unknown item type: " + info.itemType);
|
||||
}
|
||||
|
||||
// If the view is null, it has already been added.
|
||||
if (view == null) {
|
||||
cellLayout.onDragComplete();
|
||||
cellLayout.onDragExit();
|
||||
} else {
|
||||
mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
|
||||
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
|
||||
@@ -1109,7 +1092,7 @@ public class Workspace extends SmoothPagedView
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
|
||||
|
||||
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
|
||||
lp.cellX, lp.cellY);
|
||||
}
|
||||
}
|
||||
@@ -1123,23 +1106,41 @@ public class Workspace extends SmoothPagedView
|
||||
return (CellLayout) getChildAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current CellInfo describing our current drag; this method exists
|
||||
* so that Launcher can sync this object with the correct info when the activity is created/
|
||||
* destroyed
|
||||
*
|
||||
*/
|
||||
public CellLayout.CellInfo getDragInfo() {
|
||||
return mDragInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean acceptDrop(DragSource source, int x, int y,
|
||||
int xOffset, int yOffset, DragView dragView, Object dragInfo) {
|
||||
final CellLayout layout = getCurrentDropLayout();
|
||||
CellLayout layout;
|
||||
if (mIsSmall) {
|
||||
layout = findMatchingPageForDragOver(dragView, x - xOffset, y - yOffset);
|
||||
if (layout == null) {
|
||||
// cancel the drag if we're not over a mini-screen at time of drop
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
layout = getCurrentDropLayout();
|
||||
}
|
||||
final CellLayout.CellInfo dragCellInfo = mDragInfo;
|
||||
final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
|
||||
final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
|
||||
|
||||
final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
|
||||
final CellLayout.CellInfo cellInfo = layout.updateOccupiedCells(null, ignoreView);
|
||||
|
||||
if (cellInfo.findCellForSpan(mTempEstimate, spanX, spanY)) {
|
||||
if (layout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
|
||||
return true;
|
||||
} else {
|
||||
Toast.makeText(getContext(), getContext().getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
|
||||
mLauncher.showOutOfSpaceMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1156,9 +1157,9 @@ public class Workspace extends SmoothPagedView
|
||||
layout.estimateDropCell(localPixelX, localPixelY, spanX, spanY, cellXY);
|
||||
layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate);
|
||||
|
||||
final CellLayout.CellInfo cellInfo = layout.updateOccupiedCells(null, ignoreView);
|
||||
// Find the best target drop location
|
||||
return layout.findNearestVacantArea(mTempEstimate[0], mTempEstimate[1], spanX, spanY, cellInfo, recycle);
|
||||
return layout.findNearestVacantArea(
|
||||
mTempEstimate[0], mTempEstimate[1], spanX, spanY, recycle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1196,6 +1197,10 @@ public class Workspace extends SmoothPagedView
|
||||
mDragInfo = null;
|
||||
}
|
||||
|
||||
public boolean isDropEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
super.onRestoreInstanceState(state);
|
||||
@@ -1366,8 +1371,6 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
|
||||
void updateShortcuts(ArrayList<ApplicationInfo> apps) {
|
||||
final PackageManager pm = mLauncher.getPackageManager();
|
||||
|
||||
final int screenCount = getChildCount();
|
||||
for (int i = 0; i < screenCount; i++) {
|
||||
final CellLayout layout = (CellLayout) getChildAt(i);
|
||||
|
||||
Reference in New Issue
Block a user