diff options
Diffstat (limited to 'src/com/android/launcher/Workspace.java')
-rw-r--r-- | src/com/android/launcher/Workspace.java | 1211 |
1 files changed, 0 insertions, 1211 deletions
diff --git a/src/com/android/launcher/Workspace.java b/src/com/android/launcher/Workspace.java deleted file mode 100644 index 6d8eef5f1..000000000 --- a/src/com/android/launcher/Workspace.java +++ /dev/null @@ -1,1211 +0,0 @@ -/* - * Copyright (C) 2008 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.launcher; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.widget.Scroller; -import android.os.Parcelable; -import android.os.Parcel; - -import java.util.ArrayList; - -/** - * The workspace is a wide area with a wallpaper and a finite number of screens. Each - * screen contains a number of icons, folders or widgets the user can interact with. - * A workspace is meant to be used with a fixed width only. - */ -public class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller { - private static final int INVALID_SCREEN = -1; - - /** - * The velocity at which a fling gesture will cause us to snap to the next screen - */ - private static final int SNAP_VELOCITY = 1000; - - private int mDefaultScreen; - - private Paint mPaint; - private Bitmap mWallpaper; - - private int mWallpaperWidth; - private int mWallpaperHeight; - private float mWallpaperOffset; - private boolean mWallpaperLoaded; - - private boolean mFirstLayout = true; - - private int mCurrentScreen; - private int mNextScreen = INVALID_SCREEN; - private Scroller mScroller; - private VelocityTracker mVelocityTracker; - - /** - * CellInfo for the cell that is currently being dragged - */ - private CellLayout.CellInfo mDragInfo; - - private float mLastMotionX; - private float mLastMotionY; - - private final static int TOUCH_STATE_REST = 0; - private final static int TOUCH_STATE_SCROLLING = 1; - - private int mTouchState = TOUCH_STATE_REST; - - private OnLongClickListener mLongClickListener; - - private Launcher mLauncher; - private DragController mDragger; - - private int[] mTempCell = new int[2]; - - private boolean mAllowLongPress; - private boolean mLocked; - - private int mTouchSlop; - - /** - * Used to inflate the Workspace from XML. - * - * @param context The application's context. - * @param attrs The attribtues set containing the Workspace's customization values. - */ - public Workspace(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - /** - * Used to inflate the Workspace from XML. - * - * @param context The application's context. - * @param attrs The attribtues set containing the Workspace's customization values. - * @param defStyle Unused. - */ - public Workspace(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Workspace, defStyle, 0); - mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1); - a.recycle(); - - initWorkspace(); - } - - /** - * Initializes various states for this workspace. - */ - private void initWorkspace() { - mScroller = new Scroller(getContext()); - mCurrentScreen = mDefaultScreen; - Launcher.setScreen(mCurrentScreen); - - mPaint = new Paint(); - mPaint.setDither(false); - - mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); - } - - /** - * Set the background's wallpaper. - */ - void loadWallpaper(Bitmap bitmap) { - mWallpaper = bitmap; - mWallpaperLoaded = true; - requestLayout(); - invalidate(); - } - - @Override - public void addView(View child, int index, LayoutParams params) { - if (!(child instanceof CellLayout)) { - throw new IllegalArgumentException("A Workspace can only have CellLayout children."); - } - super.addView(child, index, params); - } - - @Override - public void addView(View child) { - if (!(child instanceof CellLayout)) { - throw new IllegalArgumentException("A Workspace can only have CellLayout children."); - } - super.addView(child); - } - - @Override - public void addView(View child, int index) { - if (!(child instanceof CellLayout)) { - throw new IllegalArgumentException("A Workspace can only have CellLayout children."); - } - super.addView(child, index); - } - - @Override - public void addView(View child, int width, int height) { - if (!(child instanceof CellLayout)) { - throw new IllegalArgumentException("A Workspace can only have CellLayout children."); - } - super.addView(child, width, height); - } - - @Override - public void addView(View child, LayoutParams params) { - if (!(child instanceof CellLayout)) { - throw new IllegalArgumentException("A Workspace can only have CellLayout children."); - } - super.addView(child, params); - } - - /** - * @return The open folder on the current screen, or null if there is none - */ - Folder getOpenFolder() { - CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen); - int count = currentScreen.getChildCount(); - for (int i = 0; i < count; i++) { - View child = currentScreen.getChildAt(i); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); - if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) { - return (Folder) child; - } - } - return null; - } - - ArrayList<Folder> getOpenFolders() { - final int screens = getChildCount(); - ArrayList<Folder> folders = new ArrayList<Folder>(screens); - - for (int screen = 0; screen < screens; screen++) { - CellLayout currentScreen = (CellLayout) getChildAt(screen); - int count = currentScreen.getChildCount(); - for (int i = 0; i < count; i++) { - View child = currentScreen.getChildAt(i); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); - if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) { - folders.add((Folder) child); - break; - } - } - } - - return folders; - } - - boolean isDefaultScreenShowing() { - return mCurrentScreen == mDefaultScreen; - } - - /** - * Returns the index of the currently displayed screen. - * - * @return The index of the currently displayed screen. - */ - int getCurrentScreen() { - return mCurrentScreen; - } - - /** - * 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 cellVSpan Height in cells - * @param rect Rectnagle into which to put the results - */ - public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF rect) { - ((CellLayout)getChildAt(mCurrentScreen)).cellToRect(cellX, cellY, - cellHSpan, cellVSpan, rect); - } - - /** - * Sets the current screen. - * - * @param currentScreen - */ - void setCurrentScreen(int currentScreen) { - mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1)); - scrollTo(mCurrentScreen * getWidth(), 0); - invalidate(); - } - - /** - * Shows the default screen (defined by the firstScreen attribute in XML.) - */ - void showDefaultScreen() { - setCurrentScreen(mDefaultScreen); - } - - /** - * 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, mCurrentScreen, 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, mCurrentScreen, 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. - * - * @param child The child to add in one of the workspace's screens. - * @param screen The screen in which to add the child. - * @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 addInScreen(View child, int screen, int x, int y, int spanX, int spanY) { - addInScreen(child, screen, x, y, spanX, spanY, false); - } - - /** - * Adds the specified child in the specified 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 screen The screen in which to add the child. - * @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 addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) { - if (screen < 0 || screen >= getChildCount()) { - throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount()); - } - - final CellLayout group = (CellLayout) getChildAt(screen); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); - if (lp == null) { - lp = new CellLayout.LayoutParams(x, y, spanX, spanY); - } else { - lp.cellX = x; - lp.cellY = y; - lp.cellHSpan = spanX; - lp.cellVSpan = spanY; - } - group.addView(child, insert ? 0 : -1, lp); - if (!(child instanceof Folder)) { - child.setOnLongClickListener(mLongClickListener); - } - } - - void addWidget(View view, Widget widget) { - addInScreen(view, widget.screen, widget.cellX, widget.cellY, widget.spanX, - widget.spanY, false); - } - - void addWidget(View view, Widget widget, boolean insert) { - addInScreen(view, widget.screen, widget.cellX, widget.cellY, widget.spanX, - widget.spanY, insert); - } - - CellLayout.CellInfo findAllVacantCells(boolean[] occupied) { - CellLayout group = (CellLayout) getChildAt(mCurrentScreen); - if (group != null) { - return group.findAllVacantCells(occupied); - } - return null; - } - - /** - * Returns the coordinate of a vacant cell for the current screen. - */ - boolean getVacantCell(int[] vacant, int spanX, int spanY) { - CellLayout group = (CellLayout) getChildAt(mCurrentScreen); - if (group != null) { - return group.getVacantCell(vacant, spanX, spanY); - } - return 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 spanX The number of cells spanned horizontally by the child. - * @param spanY The number of cells spanned vertically by the child. - */ - void fitInCurrentScreen(View child, int spanX, int spanY) { - fitInScreen(child, mCurrentScreen, spanX, spanY); - } - - /** - * Adds the specified child in the specified 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 screen The screen in which to add the child. - * @param spanX The number of cells spanned horizontally by the child. - * @param spanY The number of cells spanned vertically by the child. - */ - void fitInScreen(View child, int screen, int spanX, int spanY) { - if (screen < 0 || screen >= getChildCount()) { - throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount()); - } - - final CellLayout group = (CellLayout) getChildAt(screen); - boolean vacant = group.getVacantCell(mTempCell, spanX, spanY); - if (vacant) { - group.addView(child, - new CellLayout.LayoutParams(mTempCell[0], mTempCell[1], spanX, spanY)); - child.setOnLongClickListener(mLongClickListener); - if (!(child instanceof Folder)) { - child.setOnLongClickListener(mLongClickListener); - } - } - } - - /** - * Registers the specified listener on each screen contained in this workspace. - * - * @param l The listener used to respond to long clicks. - */ - @Override - public void setOnLongClickListener(OnLongClickListener l) { - mLongClickListener = l; - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - getChildAt(i).setOnLongClickListener(l); - } - } - - @Override - public void computeScroll() { - if (mScroller.computeScrollOffset()) { - mScrollX = mScroller.getCurrX(); - mScrollY = mScroller.getCurrY(); - postInvalidate(); - } else if (mNextScreen != INVALID_SCREEN) { - mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1)); - Launcher.setScreen(mCurrentScreen); - mNextScreen = INVALID_SCREEN; - clearChildrenCache(); - } - } - - @Override - protected void dispatchDraw(Canvas canvas) { - float x = mScrollX * mWallpaperOffset; - if (x + mWallpaperWidth < mRight - mLeft) { - x = mRight - mLeft - mWallpaperWidth; - } - - canvas.drawBitmap(mWallpaper, x, (mBottom - mTop - mWallpaperHeight) / 2, mPaint); - - // ViewGroup.dispatchDraw() supports many features we don't need: - // clip to padding, layout animation, animation listener, disappearing - // children, etc. The following implementation attempts to fast-track - // the drawing dispatch by drawing only what we know needs to be drawn. - - boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN; - // If we are not scrolling or flinging, draw only the current screen - if (fastDraw) { - drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime()); - } else { - final long drawingTime = getDrawingTime(); - // If we are flinging, draw only the current screen and the target screen - if (mNextScreen >= 0 && mNextScreen < getChildCount() && - Math.abs(mCurrentScreen - mNextScreen) == 1) { - drawChild(canvas, getChildAt(mCurrentScreen), drawingTime); - drawChild(canvas, getChildAt(mNextScreen), drawingTime); - } else { - // If we are scrolling, draw all of our children - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - drawChild(canvas, getChildAt(i), drawingTime); - } - } - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - final int width = MeasureSpec.getSize(widthMeasureSpec); - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); - } - - final int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); - } - - // The children are given the same width and height as the workspace - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); - } - - if (mWallpaperLoaded) { - mWallpaperLoaded = false; - mWallpaper = Utilities.centerToFit(mWallpaper, width, - MeasureSpec.getSize(heightMeasureSpec), getContext()); - mWallpaperWidth = mWallpaper.getWidth(); - mWallpaperHeight = mWallpaper.getHeight(); - } - - final int wallpaperWidth = mWallpaperWidth; - mWallpaperOffset = wallpaperWidth > width ? (count * width - wallpaperWidth) / - ((count - 1) * (float) width) : 1.0f; - - if (mFirstLayout) { - scrollTo(mCurrentScreen * width, 0); - mFirstLayout = false; - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - int childLeft = 0; - - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() != View.GONE) { - final int childWidth = child.getMeasuredWidth(); - child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); - childLeft += childWidth; - } - } - } - - @Override - public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { - int screen = indexOfChild(child); - if (screen != mCurrentScreen || !mScroller.isFinished()) { - if (!mLauncher.isWorkspaceLocked()) { - snapToScreen(screen); - } - return true; - } - return false; - } - - @Override - protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { - if (mLauncher.isDrawerDown()) { - final Folder openFolder = getOpenFolder(); - if (openFolder != null) { - return openFolder.requestFocus(direction, previouslyFocusedRect); - } else { - int focusableScreen; - if (mNextScreen != INVALID_SCREEN) { - focusableScreen = mNextScreen; - } else { - focusableScreen = mCurrentScreen; - } - getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect); - } - } - return false; - } - - @Override - public boolean dispatchUnhandledMove(View focused, int direction) { - if (direction == View.FOCUS_LEFT) { - if (getCurrentScreen() > 0) { - snapToScreen(getCurrentScreen() - 1); - return true; - } - } else if (direction == View.FOCUS_RIGHT) { - if (getCurrentScreen() < getChildCount() - 1) { - snapToScreen(getCurrentScreen() + 1); - return true; - } - } - return super.dispatchUnhandledMove(focused, direction); - } - - @Override - public void addFocusables(ArrayList<View> views, int direction) { - if (mLauncher.isDrawerDown()) { - final Folder openFolder = getOpenFolder(); - if (openFolder == null) { - getChildAt(mCurrentScreen).addFocusables(views, direction); - if (direction == View.FOCUS_LEFT) { - if (mCurrentScreen > 0) { - getChildAt(mCurrentScreen - 1).addFocusables(views, direction); - } - } else if (direction == View.FOCUS_RIGHT){ - if (mCurrentScreen < getChildCount() - 1) { - getChildAt(mCurrentScreen + 1).addFocusables(views, direction); - } - } - } else { - openFolder.addFocusables(views, direction); - } - } - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (mLocked || !mLauncher.isDrawerDown()) { - return true; - } - - /* - * This method JUST determines whether we want to intercept the motion. - * If we return true, onTouchEvent will be called and we do the actual - * scrolling there. - */ - - /* - * Shortcut the most recurring case: the user is in the dragging - * state and he is moving his finger. We want to intercept this - * motion. - */ - final int action = ev.getAction(); - if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { - return true; - } - - final float x = ev.getX(); - final float y = ev.getY(); - - switch (action) { - case MotionEvent.ACTION_MOVE: - /* - * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check - * whether the user has moved far enough from his original down touch. - */ - - /* - * Locally do absolute value. mLastMotionX is set to the y value - * of the down event. - */ - final int xDiff = (int) Math.abs(x - mLastMotionX); - final int yDiff = (int) Math.abs(y - mLastMotionY); - - final int touchSlop = mTouchSlop; - boolean xMoved = xDiff > touchSlop; - boolean yMoved = yDiff > touchSlop; - - if (xMoved || yMoved) { - - if (xMoved) { - // Scroll if the user moved far enough along the X axis - mTouchState = TOUCH_STATE_SCROLLING; - enableChildrenCache(); - } - // Either way, cancel any pending longpress - if (mAllowLongPress) { - mAllowLongPress = false; - // Try canceling the long press. It could also have been scheduled - // by a distant descendant, so use the mAllowLongPress flag to block - // everything - final View currentScreen = getChildAt(mCurrentScreen); - currentScreen.cancelLongPress(); - } - } - break; - - case MotionEvent.ACTION_DOWN: - // Remember location of down touch - mLastMotionX = x; - mLastMotionY = y; - mAllowLongPress = true; - - /* - * If being flinged and user touches the screen, initiate drag; - * otherwise don't. mScroller.isFinished should be false when - * being flinged. - */ - mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; - break; - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - // Release the drag - clearChildrenCache(); - mTouchState = TOUCH_STATE_REST; - break; - } - - /* - * The only time we want to intercept motion events is if we are in the - * drag mode. - */ - return mTouchState != TOUCH_STATE_REST; - } - - void enableChildrenCache() { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final CellLayout layout = (CellLayout) getChildAt(i); - layout.setChildrenDrawnWithCacheEnabled(true); - layout.setChildrenDrawingCacheEnabled(true); - } - } - - void clearChildrenCache() { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final CellLayout layout = (CellLayout) getChildAt(i); - layout.setChildrenDrawnWithCacheEnabled(false); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (mLocked || !mLauncher.isDrawerDown()) { - return true; - } - - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - - final int action = ev.getAction(); - final float x = ev.getX(); - - switch (action) { - case MotionEvent.ACTION_DOWN: - /* - * If being flinged and user touches, stop the fling. isFinished - * will be false if being flinged. - */ - if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - } - - // Remember where the motion event started - mLastMotionX = x; - break; - case MotionEvent.ACTION_MOVE: - if (mTouchState == TOUCH_STATE_SCROLLING) { - // Scroll to follow the motion event - final int deltaX = (int) (mLastMotionX - x); - mLastMotionX = x; - - if (deltaX < 0) { - if (mScrollX > 0) { - scrollBy(Math.max(-mScrollX, deltaX), 0); - } - } else if (deltaX > 0) { - final int availableToScroll = getChildAt(getChildCount() - 1).getRight() - - mScrollX - getWidth(); - if (availableToScroll > 0) { - scrollBy(Math.min(availableToScroll, deltaX), 0); - } - } - } - break; - case MotionEvent.ACTION_UP: - if (mTouchState == TOUCH_STATE_SCROLLING) { - final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000); - int velocityX = (int) velocityTracker.getXVelocity(); - - if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { - // Fling hard enough to move left - snapToScreen(mCurrentScreen - 1); - } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) { - // Fling hard enough to move right - snapToScreen(mCurrentScreen + 1); - } else { - snapToDestination(); - } - - if (mVelocityTracker != null) { - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - } - mTouchState = TOUCH_STATE_REST; - break; - case MotionEvent.ACTION_CANCEL: - mTouchState = TOUCH_STATE_REST; - } - - return true; - } - - private void snapToDestination() { - final int screenWidth = getWidth(); - final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth; - - snapToScreen(whichScreen); - } - - void snapToScreen(int whichScreen) { - enableChildrenCache(); - - whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); - boolean changingScreens = whichScreen != mCurrentScreen; - - mNextScreen = whichScreen; - - View focusedChild = getFocusedChild(); - if (focusedChild != null && changingScreens && focusedChild == getChildAt(mCurrentScreen)) { - focusedChild.clearFocus(); - } - - final int newX = whichScreen * getWidth(); - final int delta = newX - mScrollX; - mScroller.startScroll(mScrollX, 0, delta, 0, Math.abs(delta) * 2); - invalidate(); - } - - void startDrag(CellLayout.CellInfo cellInfo) { - View child = cellInfo.cell; - - // Make sure the drag was started by a long press as opposed to a long click. - // Note that Search takes focus when clicked rather than entering touch mode - if (!child.isInTouchMode() && !(child instanceof Search)) { - return; - } - - mDragInfo = cellInfo; - mDragInfo.screen = mCurrentScreen; - - CellLayout current = ((CellLayout) getChildAt(mCurrentScreen)); - - current.onDragChild(child); - mDragger.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE); - invalidate(); - } - - @Override - protected Parcelable onSaveInstanceState() { - final SavedState state = new SavedState(super.onSaveInstanceState()); - state.currentScreen = mCurrentScreen; - return state; - } - - @Override - protected void onRestoreInstanceState(Parcelable state) { - SavedState savedState = (SavedState) state; - super.onRestoreInstanceState(savedState.getSuperState()); - if (savedState.currentScreen != -1) { - mCurrentScreen = savedState.currentScreen; - Launcher.setScreen(mCurrentScreen); - } - } - - void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo) { - addApplicationShortcut(info, cellInfo, false); - } - - void addApplicationShortcut(ApplicationInfo 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, Object dragInfo) { - final CellLayout cellLayout = (CellLayout) getChildAt(mCurrentScreen); - if (source != this) { - onDropExternal(x - xOffset, y - yOffset, dragInfo, cellLayout); - } else { - // Move internally - if (mDragInfo != null) { - final View cell = mDragInfo.cell; - if (mCurrentScreen != mDragInfo.screen) { - final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen); - originalCellLayout.removeView(cell); - cellLayout.addView(cell); - } - cellLayout.onDropChild(cell, x - xOffset, y - yOffset); - - final ItemInfo info = (ItemInfo)cell.getTag(); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams(); - LauncherModel.moveItemInDatabase(mLauncher, info, - LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY); - } - } - } - - public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, - Object dragInfo) { - } - - public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, - Object dragInfo) { - } - - public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, - Object dragInfo) { - } - - private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout) { - onDropExternal(x, y, dragInfo, cellLayout, false); - } - - private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout, - boolean insertAtFirst) { - // Drag from somewhere else - ItemInfo info = (ItemInfo) dragInfo; - - View view; - - switch (info.itemType) { - case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: - case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: - if (info.container == NO_ID) { - // Came from all apps -- make a copy - info = new ApplicationInfo((ApplicationInfo) info); - } - view = mLauncher.createShortcut(R.layout.application, cellLayout, - (ApplicationInfo) info); - break; - case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER: - view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, - (ViewGroup) getChildAt(mCurrentScreen), ((UserFolderInfo) info)); - break; - default: - throw new IllegalStateException("Unknown item type: " + info.itemType); - } - - cellLayout.addView(view, insertAtFirst ? 0 : -1); - view.setOnLongClickListener(mLongClickListener); - cellLayout.onDropChild(view, x, y); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); - - final LauncherModel model = Launcher.getModel(); - model.addDesktopItem(info); - LauncherModel.addOrMoveItemInDatabase(mLauncher, info, - LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY); - } - - public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, - Object dragInfo) { - - final CellLayout.CellInfo cellInfo = mDragInfo; - int cellHSpan = cellInfo == null ? 1 : cellInfo.spanX; - int cellVSpan = cellInfo == null ? 1 : cellInfo.spanY; - - return ((CellLayout) getChildAt(mCurrentScreen)).acceptChildDrop(x - xOffset, y - yOffset, - cellHSpan, cellVSpan, cellInfo == null ? null : cellInfo.cell); - } - - void setLauncher(Launcher launcher) { - mLauncher = launcher; - } - - public void setDragger(DragController dragger) { - mDragger = dragger; - } - - public void onDropCompleted(View target, boolean success) { - if (success){ - if (target != this && mDragInfo != null) { - final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen); - cellLayout.removeView(mDragInfo.cell); - final Object tag = mDragInfo.cell.getTag(); - Launcher.getModel().removeDesktopItem((ItemInfo) tag); - } - } else { - if (mDragInfo != null) { - final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen); - cellLayout.onDropAborted(mDragInfo.cell); - } - } - - mDragInfo = null; - } - - public void scrollLeft() { - if (mNextScreen == INVALID_SCREEN && mCurrentScreen > 0 && mScroller.isFinished()) { - snapToScreen(mCurrentScreen - 1); - } - } - - public void scrollRight() { - if (mNextScreen == INVALID_SCREEN && mCurrentScreen < getChildCount() -1 && - mScroller.isFinished()) { - snapToScreen(mCurrentScreen + 1); - } - } - - public int getScreenForView(View v) { - int result = -1; - if (v != null) { - ViewParent vp = v.getParent(); - int count = getChildCount(); - for (int i = 0; i < count; i++) { - if (vp == getChildAt(i)) { - return i; - } - } - } - return result; - } - - /** - * Find a search widget on the given screen - */ - private View findSearchWidget(CellLayout screen) { - final int count = screen.getChildCount(); - for (int i = 0; i < count; i++) { - View v = screen.getChildAt(i); - if (v instanceof Search) { - return v; - } - } - return null; - } - - /** - * Focuses on the search widget on the specified screen, - * if there is one. Also clears the current search selection so we don't - */ - private boolean focusOnSearch(int screen) { - CellLayout currentScreen = (CellLayout)getChildAt(screen); - Search searchWidget = (Search)findSearchWidget(currentScreen); - if (searchWidget != null) { - if (isInTouchMode()) { - searchWidget.requestFocusFromTouch(); - } else { - searchWidget.requestFocus(); - } - searchWidget.clearQuery(); - return true; - } - return false; - } - - /** - * Snap to the nearest screen with a search widget and give it focus - * - * @return True if a search widget was found - */ - public boolean snapToSearch() { - // The screen we are searching - int current = mCurrentScreen; - - // first position scanned so far - int first = current; - - // last position scanned so far - int last = current; - - // True if we should move down on the next iteration - boolean next = false; - - // True when we have looked at the first item in the data - boolean hitFirst; - - // True when we have looked at the last item in the data - boolean hitLast; - - final int count = getChildCount(); - - while (true) { - if (focusOnSearch(current)) { - return true; - } - - hitLast = last == count - 1; - hitFirst = first == 0; - - if (hitLast && hitFirst) { - // Looked at everything - break; - } - - if (hitFirst || (next && !hitLast)) { - // Either we hit the top, or we are trying to move down - last++; - current = last; - // Try going up next time - next = false; - } else { - // Either we hit the bottom, or we are trying to move up - first--; - current = first; - // Try going down next time - next = true; - } - - } - return false; - } - - public Folder getFolderForTag(Object tag) { - int screenCount = getChildCount(); - for (int screen = 0; screen < screenCount; screen++) { - CellLayout currentScreen = ((CellLayout) getChildAt(screen)); - int count = currentScreen.getChildCount(); - for (int i = 0; i < count; i++) { - View child = currentScreen.getChildAt(i); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); - if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) { - Folder f = (Folder) child; - if (f.getInfo() == tag) { - return f; - } - } - } - } - return null; - } - - public View getViewForTag(Object tag) { - int screenCount = getChildCount(); - for (int screen = 0; screen < screenCount; screen++) { - CellLayout currentScreen = ((CellLayout) getChildAt(screen)); - int count = currentScreen.getChildCount(); - for (int i = 0; i < count; i++) { - View child = currentScreen.getChildAt(i); - if (child.getTag() == tag) { - return child; - } - } - } - return null; - } - - /** - * Unlocks the SlidingDrawer so that touch events are processed. - * - * @see #lock() - */ - public void unlock() { - mLocked = false; - } - - /** - * Locks the SlidingDrawer so that touch events are ignores. - * - * @see #unlock() - */ - public void lock() { - mLocked = true; - } - - /** - * @return True is long presses are still allowed for the current touch - */ - public boolean allowLongPress() { - return mAllowLongPress; - } - - void removeShortcutsForPackage(String packageName) { - final ArrayList<View> childrenToRemove = new ArrayList<View>(); - final LauncherModel model = Launcher.getModel(); - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final CellLayout layout = (CellLayout) getChildAt(i); - int childCount = layout.getChildCount(); - childrenToRemove.clear(); - for (int j = 0; j < childCount; j++) { - final View view = layout.getChildAt(j); - Object tag = view.getTag(); - if (tag instanceof ApplicationInfo) { - ApplicationInfo info = (ApplicationInfo) tag; - if (packageName.equals(info.intent.getComponent().getPackageName())) { - model.removeDesktopItem(info); - LauncherModel.deleteItemFromDatabase(mLauncher, info); - childrenToRemove.add(view); - } - } - } - childCount = childrenToRemove.size(); - for (int j = 0; j < childCount; j++) { - layout.removeViewInLayout(childrenToRemove.get(j)); - } - if (childCount > 0) { - layout.requestLayout(); - layout.invalidate(); - } - } - } - - // TODO: remove gadgets when gadgetmanager tells us they're gone -// void removeGadgetsForProvider() { -// } - - void moveToDefaultScreen() { - snapToScreen(mDefaultScreen); - getChildAt(mDefaultScreen).requestFocus(); - } - - public static class SavedState extends BaseSavedState { - int currentScreen = -1; - - SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - currentScreen = in.readInt(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeInt(currentScreen); - } - - public static final Parcelable.Creator<SavedState> CREATOR = - new Parcelable.Creator<SavedState>() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } -} |