Allow for NxM layout and in-place rotation of items on homescreen.

Currently, rotation is disabled as designs are still in flux, but the NxM grid is enabled (8x4).

Change-Id: I0026f88c674719e3d67de6d6d481d2d4cd606362
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 73481c2..d69c56f 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -16,36 +16,44 @@
 
 package com.android.launcher2;
 
+import java.util.ArrayList;
+
+import android.app.WallpaperManager;
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.graphics.Canvas;
 import android.util.AttributeSet;
 import android.view.ContextMenu;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
-import android.app.WallpaperManager;
-
-import java.util.ArrayList;
+import android.view.animation.Animation;
+import android.view.animation.LayoutAnimationController;
 
 import com.android.launcher.R;
 
 public class CellLayout extends ViewGroup {
+    static final String TAG = "CellLayout";
+
     private boolean mPortrait;
 
     private int mCellWidth;
     private int mCellHeight;
-    
+
     private int mLongAxisStartPadding;
     private int mLongAxisEndPadding;
-
     private int mShortAxisStartPadding;
     private int mShortAxisEndPadding;
 
+    private int mLeftPadding;
+    private int mRightPadding;
+    private int mTopPadding;
+    private int mBottomPadding;
+
     private int mShortAxisCells;
     private int mLongAxisCells;
 
@@ -54,7 +62,7 @@
 
     private final Rect mRect = new Rect();
     private final CellInfo mCellInfo = new CellInfo();
-    
+
     int[] mCellXY = new int[2];
     boolean[][] mOccupied;
 
@@ -62,8 +70,8 @@
 
     private boolean mDirtyTag;
     private boolean mLastDownOnOccupiedCell = false;
-    
-    private final WallpaperManager mWallpaperManager;     
+
+    private final WallpaperManager mWallpaperManager;
 
     public CellLayout(Context context) {
         this(context, null);
@@ -79,16 +87,16 @@
 
         mCellWidth = a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10);
         mCellHeight = a.getDimensionPixelSize(R.styleable.CellLayout_cellHeight, 10);
-        
-        mLongAxisStartPadding = 
+
+        mLongAxisStartPadding =
             a.getDimensionPixelSize(R.styleable.CellLayout_longAxisStartPadding, 10);
-        mLongAxisEndPadding = 
+        mLongAxisEndPadding =
             a.getDimensionPixelSize(R.styleable.CellLayout_longAxisEndPadding, 10);
         mShortAxisStartPadding =
             a.getDimensionPixelSize(R.styleable.CellLayout_shortAxisStartPadding, 10);
-        mShortAxisEndPadding = 
+        mShortAxisEndPadding =
             a.getDimensionPixelSize(R.styleable.CellLayout_shortAxisEndPadding, 10);
-        
+
         mShortAxisCells = a.getInt(R.styleable.CellLayout_shortAxisCells, 4);
         mLongAxisCells = a.getInt(R.styleable.CellLayout_longAxisCells, 4);
 
@@ -96,14 +104,6 @@
 
         setAlwaysDrawnWithCacheEnabled(false);
 
-        if (mOccupied == null) {
-            if (mPortrait) {
-                mOccupied = new boolean[mShortAxisCells][mLongAxisCells];
-            } else {
-                mOccupied = new boolean[mLongAxisCells][mShortAxisCells];
-            }
-        }
-        
         mWallpaperManager = WallpaperManager.getInstance(getContext());
     }
 
@@ -132,14 +132,24 @@
         return mPortrait ? mLongAxisCells : mShortAxisCells;
     }
 
-    @Override
-    public void addView(View child, int index, ViewGroup.LayoutParams params) {
+    // Takes canonical layout parameters
+    public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params) {
+        final LayoutParams lp = params;
+
         // Generate an id for each view, this assumes we have at most 256x256 cells
         // per workspace screen
-        final LayoutParams lp = (LayoutParams) params;
-        child.setId(((getId() & 0xFF) << 16) | (lp.cellX & 0xFF) << 8 | (lp.cellY & 0xFF));
+        if (lp.cellX >= 0 && lp.cellX <= getCountX() - 1 && lp.cellY >= 0 && lp.cellY <= getCountY() - 1) {
+            // If the horizontal or vertical span is set to -1, it is taken to
+            // mean that it spans the extent of the CellLayout
+            if (lp.cellHSpan < 0) lp.cellHSpan = getCountX();
+            if (lp.cellVSpan < 0) lp.cellVSpan = getCountY();
 
-        super.addView(child, index, params);
+            child.setId(childId);
+
+            addView(child, index, lp);
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -185,7 +195,7 @@
                 }
             }
         }
-            
+
         mLastDownOnOccupiedCell = found;
 
         if (!found) {
@@ -217,6 +227,7 @@
         setTag(cellInfo);
     }
 
+
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
@@ -256,8 +267,8 @@
         return info;
     }
 
-    private static void findIntersectingVacantCells(CellInfo cellInfo, int x, int y,
-            int xCount, int yCount, boolean[][] occupied) {
+    private static void findIntersectingVacantCells(CellInfo cellInfo, int x,
+            int y, int xCount, int yCount, boolean[][] occupied) {
 
         cellInfo.maxVacantSpanX = Integer.MIN_VALUE;
         cellInfo.maxVacantSpanXSpanY = Integer.MIN_VALUE;
@@ -392,21 +403,21 @@
 
         // 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 
+     * Given a point, return the cell that strictly encloses that point
      * @param x X coordinate of the point
      * @param y Y coordinate of the point
      * @param result Array of 2 ints to hold the x and y coordinate of the cell
      */
     void pointToCellExact(int x, int y, int[] result) {
         final boolean portrait = mPortrait;
-        
-        final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
-        final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
+
+        final int hStartPadding = getLeftPadding();
+        final int vStartPadding = getTopPadding();
 
         result[0] = (x - hStartPadding) / (mCellWidth + mWidthGap);
         result[1] = (y - vStartPadding) / (mCellHeight + mHeightGap);
@@ -419,7 +430,7 @@
         if (result[1] < 0) result[1] = 0;
         if (result[1] >= yAxis) result[1] = yAxis - 1;
     }
-    
+
     /**
      * Given a point, return the cell that most closely encloses that point
      * @param x X coordinate of the point
@@ -432,18 +443,15 @@
 
     /**
      * Given a cell coordinate, return the point that represents the upper left corner of that cell
-     * 
-     * @param cellX X coordinate of the cell 
+     *
+     * @param cellX X coordinate of the cell
      * @param cellY Y coordinate of the cell
-     * 
+     *
      * @param result Array of 2 ints to hold the x and y coordinate of the point
      */
     void cellToPoint(int cellX, int cellY, int[] result) {
-        final boolean portrait = mPortrait;
-        
-        final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
-        final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
-
+        final int hStartPadding = getLeftPadding();
+        final int vStartPadding = getTopPadding();
 
         result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap);
         result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap);
@@ -458,92 +466,117 @@
     }
 
     int getLeftPadding() {
-        return mPortrait ? mShortAxisStartPadding : mLongAxisStartPadding;
+        return mLeftPadding;
     }
 
     int getTopPadding() {
-        return mPortrait ? mLongAxisStartPadding : mShortAxisStartPadding;        
+        return mTopPadding;
     }
 
     int getRightPadding() {
-        return mPortrait ? mShortAxisEndPadding : mLongAxisEndPadding;
+        return mRightPadding;
     }
 
     int getBottomPadding() {
-        return mPortrait ? mLongAxisEndPadding : mShortAxisEndPadding;        
+        return mBottomPadding;
     }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // TODO: currently ignoring padding
-        
+
         int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
-        int widthSpecSize =  MeasureSpec.getSize(widthMeasureSpec);
-        
+        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+
         int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
         int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
-        
+
         if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
             throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
         }
 
         final int shortAxisCells = mShortAxisCells;
         final int longAxisCells = mLongAxisCells;
-        final int longAxisStartPadding = mLongAxisStartPadding;
-        final int longAxisEndPadding = mLongAxisEndPadding;
-        final int shortAxisStartPadding = mShortAxisStartPadding;
-        final int shortAxisEndPadding = mShortAxisEndPadding;
         final int cellWidth = mCellWidth;
         final int cellHeight = mCellHeight;
 
-        mPortrait = heightSpecSize > widthSpecSize;
+        boolean portrait = heightSpecSize > widthSpecSize;
+        if (portrait != mPortrait || mOccupied == null) {
+            if (portrait) {
+                mOccupied = new boolean[mShortAxisCells][mLongAxisCells];
+            } else {
+                mOccupied = new boolean[mLongAxisCells][mShortAxisCells];
+            }
+        }
+        mPortrait = portrait;
 
         int numShortGaps = shortAxisCells - 1;
         int numLongGaps = longAxisCells - 1;
 
         if (mPortrait) {
-            int vSpaceLeft = heightSpecSize - longAxisStartPadding - longAxisEndPadding
-                    - (cellHeight * longAxisCells);
+            int vSpaceLeft = heightSpecSize - mLongAxisStartPadding
+                    - mLongAxisEndPadding - (cellHeight * longAxisCells);
             mHeightGap = vSpaceLeft / numLongGaps;
 
-            int hSpaceLeft = widthSpecSize - shortAxisStartPadding - shortAxisEndPadding
-                    - (cellWidth * shortAxisCells);
+            int hSpaceLeft = widthSpecSize - mShortAxisStartPadding
+                    - mShortAxisEndPadding - (cellWidth * shortAxisCells);
             if (numShortGaps > 0) {
                 mWidthGap = hSpaceLeft / numShortGaps;
             } else {
                 mWidthGap = 0;
             }
+
+            if (LauncherApplication.isInPlaceRotationEnabled()) {
+                mWidthGap = mHeightGap = Math.min(mHeightGap, mWidthGap);
+                mLeftPadding = mRightPadding = (widthSpecSize - cellWidth
+                        * shortAxisCells - (shortAxisCells - 1) * mWidthGap) / 2;
+                mTopPadding = mBottomPadding = (heightSpecSize - cellHeight
+                        * longAxisCells - (longAxisCells - 1) * mHeightGap) / 2;
+            } else {
+                mLeftPadding = mShortAxisStartPadding;
+                mRightPadding = mShortAxisEndPadding;
+                mTopPadding = mLongAxisStartPadding;
+                mBottomPadding = mLongAxisEndPadding;
+            }
         } else {
-            int hSpaceLeft = widthSpecSize - longAxisStartPadding - longAxisEndPadding
-                    - (cellWidth * longAxisCells);
+            int hSpaceLeft = widthSpecSize - mLongAxisStartPadding
+                    - mLongAxisEndPadding - (cellWidth * longAxisCells);
             mWidthGap = hSpaceLeft / numLongGaps;
 
-            int vSpaceLeft = heightSpecSize - shortAxisStartPadding - shortAxisEndPadding
-                    - (cellHeight * shortAxisCells);
+            int vSpaceLeft = heightSpecSize - mShortAxisStartPadding
+                    - mShortAxisEndPadding - (cellHeight * shortAxisCells);
             if (numShortGaps > 0) {
                 mHeightGap = vSpaceLeft / numShortGaps;
             } else {
                 mHeightGap = 0;
             }
+
+            if (LauncherApplication.isScreenXLarge()) {
+                mWidthGap = mHeightGap = Math.min(mHeightGap, mWidthGap);
+                mLeftPadding = mRightPadding = (widthSpecSize - cellWidth
+                        * longAxisCells - (longAxisCells - 1) * mWidthGap) / 2 ;
+                mTopPadding = mBottomPadding = (heightSpecSize - cellHeight
+                        * shortAxisCells - (shortAxisCells - 1) * mHeightGap) / 2;
+            } else {
+                mLeftPadding = mLongAxisStartPadding;
+                mRightPadding = mLongAxisEndPadding;
+                mTopPadding = mShortAxisStartPadding;
+                mBottomPadding = mShortAxisEndPadding;
+            }
         }
-        
         int count = getChildCount();
 
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
             LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
+                    mLeftPadding, mTopPadding);
 
-            if (mPortrait) {
-                lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, shortAxisStartPadding,
-                        longAxisStartPadding);
-            } else {
-                lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap, longAxisStartPadding,
-                        shortAxisStartPadding);
-            }
-            
-            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
-            int childheightMeasureSpec =
-                    MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
+            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width,
+                    MeasureSpec.EXACTLY);
+            int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
+                    MeasureSpec.EXACTLY);
+
             child.measure(childWidthMeasureSpec, childheightMeasureSpec);
         }
 
@@ -596,7 +629,7 @@
     /**
      * Find a vacant area that will fit the given bounds nearest the requested
      * cell location. Uses Euclidean distance to score multiple vacant areas.
-     * 
+     *
      * @param pixelX The X location at which you want to search for a vacant area.
      * @param pixelY The Y location at which you want to search for a vacant area.
      * @param spanX Horizontal span of the object.
@@ -608,12 +641,12 @@
      */
     int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY,
             CellInfo vacantCells, int[] recycle) {
-        
+
         // Keep track of best-scoring drop area
         final int[] bestXY = recycle != null ? recycle : new int[2];
         final int[] cellXY = mCellXY;
         double bestDistance = Double.MAX_VALUE;
-        
+
         // Bail early if vacant cells aren't valid
         if (!vacantCells.valid) {
             return null;
@@ -623,17 +656,17 @@
         final int size = vacantCells.vacantCells.size();
         for (int i = 0; i < size; i++) {
             final CellInfo.VacantCell cell = vacantCells.vacantCells.get(i);
-            
+
             // Reject if vacant cell isn't our exact size
             if (cell.spanX != spanX || cell.spanY != spanY) {
                 continue;
             }
-            
+
             // Score is center distance from requested pixel
             cellToPoint(cell.cellX, cell.cellY, cellXY);
-            
-            double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2) +
-                    Math.pow(cellXY[1] - pixelY, 2));
+
+            double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
+                    + Math.pow(cellXY[1] - pixelY, 2));
             if (distance <= bestDistance) {
                 bestDistance = distance;
                 bestXY[0] = cell.cellX;
@@ -641,25 +674,22 @@
             }
         }
 
-        // Return null if no suitable location found 
+        // Return null if no suitable location found
         if (bestDistance < Double.MAX_VALUE) {
             return bestXY;
         } else {
             return null;
         }
     }
-    
+
     /**
-     * Drop a child at the specified position
+     * Mark a child as having been dropped.
      *
      * @param child The child that is being dropped
-     * @param targetXY Destination area to move to
      */
-    void onDropChild(View child, int[] targetXY) {
+    void onDropChild(View child) {
         if (child != null) {
             LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            lp.cellX = targetXY[0];
-            lp.cellY = targetXY[1];
             lp.isDragging = false;
             lp.dropped = true;
             mDragRect.setEmpty();
@@ -678,7 +708,7 @@
 
     /**
      * Start dragging the specified child
-     * 
+     *
      * @param child The child that is being dragged
      */
     void onDragChild(View child) {
@@ -686,13 +716,13 @@
         lp.isDragging = true;
         mDragRect.setEmpty();
     }
-    
+
     /**
      * Drag a child over the specified position
-     * 
+     *
      * @param child The child that is being dropped
      * @param cellX The child's new x cell location
-     * @param cellY The child's new y cell location 
+     * @param cellY The child's new y cell location
      */
     void onDragOverChild(View child, int cellX, int cellY) {
         int[] cellXY = mCellXY;
@@ -701,39 +731,38 @@
         cellToRect(cellXY[0], cellXY[1], lp.cellHSpan, lp.cellVSpan, mDragRect);
         invalidate();
     }
-    
+
     /**
      * Computes a bounding rectangle for a range of cells
-     *  
+     *
      * @param cellX X coordinate of upper left corner expressed as a cell position
      * @param cellY Y coordinate of upper left corner expressed as a cell position
-     * @param cellHSpan Width in cells 
+     * @param cellHSpan Width in cells
      * @param cellVSpan Height in cells
      * @param dragRect Rectnagle into which to put the results
      */
     public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF dragRect) {
-        final boolean portrait = mPortrait;
         final int cellWidth = mCellWidth;
         final int cellHeight = mCellHeight;
         final int widthGap = mWidthGap;
         final int heightGap = mHeightGap;
-        
-        final int hStartPadding = portrait ? mShortAxisStartPadding : mLongAxisStartPadding;
-        final int vStartPadding = portrait ? mLongAxisStartPadding : mShortAxisStartPadding;
-        
+
+        final int hStartPadding = getLeftPadding();
+        final int vStartPadding = getTopPadding();
+
         int width = cellHSpan * cellWidth + ((cellHSpan - 1) * widthGap);
         int height = cellVSpan * cellHeight + ((cellVSpan - 1) * heightGap);
 
         int x = hStartPadding + cellX * (cellWidth + widthGap);
         int y = vStartPadding + cellY * (cellHeight + heightGap);
-        
+
         dragRect.set(x, y, x + width, y + height);
     }
-    
+
     /**
-     * Computes the required horizontal and vertical cell spans to always 
+     * Computes the required horizontal and vertical cell spans to always
      * fit the given rectangle.
-     *  
+     *
      * @param width Width in pixels
      * @param height Height in pixels
      */
@@ -758,7 +787,7 @@
      * @param vacant Holds the x and y coordinate of the vacant cell
      * @param spanX Horizontal cell span.
      * @param spanY Vertical cell span.
-     * 
+     *
      * @return True if a vacant cell was found
      */
     public boolean getVacantCell(int[] vacant, int spanX, int spanY) {
@@ -852,6 +881,17 @@
         return new CellLayout.LayoutParams(p);
     }
 
+    public static class CellLayoutAnimationController extends LayoutAnimationController {
+        public CellLayoutAnimationController(Animation animation, float delay) {
+            super(animation, delay);
+        }
+
+        @Override
+        protected long getDelayForView(View view) {
+            return (int) (Math.random() * 150);
+        }
+    }
+
     public static class LayoutParams extends ViewGroup.MarginLayoutParams {
         /**
          * Horizontal location of the item in the grid.
@@ -876,7 +916,7 @@
          */
         @ViewDebug.ExportedProperty
         public int cellVSpan;
-        
+
         /**
          * Is this item currently being dragged
          */
@@ -902,7 +942,15 @@
             cellHSpan = 1;
             cellVSpan = 1;
         }
-        
+
+        public LayoutParams(LayoutParams source) {
+            super(source);
+            this.cellX = source.cellX;
+            this.cellY = source.cellY;
+            this.cellHSpan = source.cellHSpan;
+            this.cellVSpan = source.cellVSpan;
+        }
+
         public LayoutParams(int cellX, int cellY, int cellHSpan, int cellVSpan) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             this.cellX = cellX;
@@ -913,12 +961,12 @@
 
         public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
                 int hStartPadding, int vStartPadding) {
-            
+
             final int myCellHSpan = cellHSpan;
             final int myCellVSpan = cellVSpan;
             final int myCellX = cellX;
             final int myCellY = cellY;
-            
+
             width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
                     leftMargin - rightMargin;
             height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
@@ -927,14 +975,18 @@
             x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
             y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
         }
+
+        public String toString() {
+            return "(" + this.cellX + ", " + this.cellY + ")";
+        }
     }
 
     static final class CellInfo implements ContextMenu.ContextMenuInfo {
         /**
-         * See View.AttachInfo.InvalidateInfo for futher explanations about
-         * the recycling mechanism. In this case, we recycle the vacant cells
-         * instances because up to several hundreds can be instanciated when
-         * the user long presses an empty cell.
+         * See View.AttachInfo.InvalidateInfo for futher explanations about the
+         * recycling mechanism. In this case, we recycle the vacant cells
+         * instances because up to several hundreds can be instanciated when the
+         * user long presses an empty cell.
          */
         static final class VacantCell {
             int cellX;
@@ -945,7 +997,7 @@
             // We can create up to 523 vacant cells on a 4x4 grid, 100 seems
             // like a reasonable compromise given the size of a VacantCell and
             // the fact that the user is not likely to touch an empty 4x4 grid
-            // very often 
+            // very often
             private static final int POOL_LIMIT = 100;
             private static final Object sLock = new Object();
 
@@ -980,8 +1032,8 @@
 
             @Override
             public String toString() {
-                return "VacantCell[x=" + cellX + ", y=" + cellY + ", spanX=" + spanX +
-                        ", spanY=" + spanY + "]";
+                return "VacantCell[x=" + cellX + ", y=" + cellY + ", spanX="
+                        + spanX + ", spanY=" + spanY + "]";
             }
         }
 
@@ -1004,7 +1056,9 @@
             final ArrayList<VacantCell> list = vacantCells;
             final int count = list.size();
 
-            for (int i = 0; i < count; i++) list.get(i).release();
+            for (int i = 0; i < count; i++) {
+                list.get(i).release();
+            }
 
             list.clear();
         }
@@ -1078,15 +1132,17 @@
                 }
             }
 
-            if (clear) clearVacantCells();
+            if (clear) {
+                clearVacantCells();
+            }
 
             return found;
         }
 
         @Override
         public String toString() {
-            return "Cell[view=" + (cell == null ? "null" : cell.getClass()) + ", x=" + cellX +
-                    ", y=" + cellY + "]";
+            return "Cell[view=" + (cell == null ? "null" : cell.getClass())
+                    + ", x=" + cellX + ", y=" + cellY + "]";
         }
     }
 
@@ -1094,5 +1150,3 @@
         return mLastDownOnOccupiedCell;
     }
 }
-
-