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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user