summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher/Workspace.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher/Workspace.java')
-rw-r--r--src/com/android/launcher/Workspace.java1211
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];
- }
- };
- }
-}