diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher2/AllAppsPagedView.java | 1 | ||||
-rw-r--r-- | src/com/android/launcher2/CellLayout.java | 66 | ||||
-rw-r--r-- | src/com/android/launcher2/CustomizePagedView.java | 18 | ||||
-rw-r--r-- | src/com/android/launcher2/DragController.java | 59 | ||||
-rw-r--r-- | src/com/android/launcher2/DragView.java | 30 | ||||
-rw-r--r-- | src/com/android/launcher2/FolderListAdapter.java | 36 | ||||
-rw-r--r-- | src/com/android/launcher2/IntentListAdapter.java | 83 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 45 | ||||
-rw-r--r-- | src/com/android/launcher2/WidgetListAdapter.java | 135 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 174 |
10 files changed, 333 insertions, 314 deletions
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java index 72eeb22..be3135c 100644 --- a/src/com/android/launcher2/AllAppsPagedView.java +++ b/src/com/android/launcher2/AllAppsPagedView.java @@ -181,7 +181,6 @@ public class AllAppsPagedView extends PagedView app = new ApplicationInfo(app); mDragController.startDrag(v, this, app, DragController.DRAG_ACTION_COPY); - mLauncher.closeAllApps(true); return true; } diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index e86b305..4c08ca6 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -24,6 +24,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; @@ -81,10 +82,15 @@ public class CellLayout extends ViewGroup { private Bitmap mDimmedBitmap; private Canvas mDimmedBitmapCanvas; private float mDimmedBitmapAlpha; - private boolean mDimmedBitmapDirty; + private boolean mDimmedBitmapDirty = false; private final Paint mDimmedBitmapPaint = new Paint(); private final Rect mLayoutRect = new Rect(); private final Rect mDimmedBitmapRect = new Rect(); + private Drawable mDimmedBitmapBackground; + private Drawable mDimmedBitmapBackgroundHover; + // If we're actively dragging something over this screen and it's small, + // mHover is true + private boolean mHover = false; private final RectF mDragRect = new RectF(); @@ -122,6 +128,14 @@ public class CellLayout extends ViewGroup { mVacantDrawable = getResources().getDrawable(R.drawable.rounded_rect_green); mOccupiedDrawable = getResources().getDrawable(R.drawable.rounded_rect_red); + if (LauncherApplication.isScreenXLarge()) { + mDimmedBitmapBackground = getResources().getDrawable( + R.drawable.mini_home_screen_bg); + + mDimmedBitmapBackgroundHover = getResources().getDrawable( + R.drawable.mini_home_screen_bg_hover); + } + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0); mCellWidth = a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10); @@ -148,8 +162,20 @@ public class CellLayout extends ViewGroup { mDimmedBitmapPaint.setFilterBitmap(true); } + public void setHover(boolean value) { + if (mHover != value) { + invalidate(); + } + mHover = value; + } + @Override public void dispatchDraw(Canvas canvas) { + if (mDimmedBitmapAlpha > 0.0f) { + final Drawable bg = mHover ? mDimmedBitmapBackgroundHover : mDimmedBitmapBackground; + bg.setAlpha((int) (mDimmedBitmapAlpha * 255)); + bg.draw(canvas); + } super.dispatchDraw(canvas); } @@ -567,6 +593,12 @@ public class CellLayout extends ViewGroup { super.onSizeChanged(w, h, oldw, oldh); mLayoutRect.set(0, 0, w, h); mDimmedBitmapRect.set(0, 0, (int) (DIMMED_BITMAP_SCALE * w), (int) (DIMMED_BITMAP_SCALE * h)); + if (mDimmedBitmapBackground != null) { + mDimmedBitmapBackground.setBounds(mLayoutRect); + } + if (mDimmedBitmapBackgroundHover != null) { + mDimmedBitmapBackgroundHover.setBounds(mLayoutRect); + } } @Override @@ -619,19 +651,12 @@ public class CellLayout extends ViewGroup { // draw the screen into the bitmap // just for drawing to the bitmap, make all the items on the screen opaque setChildrenAlpha(1.0f); - dispatchDraw(mDimmedBitmapCanvas); + // call our superclass's dispatchdraw so we don't draw the background + super.dispatchDraw(mDimmedBitmapCanvas); setChildrenAlpha(1.0f - mDimmedBitmapAlpha); - // make the bitmap 'dimmed' ie colored regions are dark grey, - // the rest is light grey - // We draw grey to the whole bitmap, but filter where we draw based on - // what regions are transparent or not (SRC_OUT), causing the intended effect - - // First, draw light grey everywhere in the background (currently transparent) regions - // This will leave the regions with the widgets as mostly transparent - mDimmedBitmapCanvas.drawColor(0xCCCCCCCC, PorterDuff.Mode.SRC_OUT); - // Now, fill the the remaining transparent regions with dark grey - mDimmedBitmapCanvas.drawColor(0xCC333333, PorterDuff.Mode.SRC_OUT); + // replace all colored areas with a dark (semi-transparent black) + mDimmedBitmapCanvas.drawColor(Color.argb(160, 0, 0, 0), PorterDuff.Mode.SRC_IN); } private boolean isVacant(int originX, int originY, int spanX, int spanY) { @@ -683,9 +708,9 @@ public class CellLayout extends ViewGroup { final int countX = mCountX; final int countY = mCountY; - // originX and originY give the top left of the cell, but pointToCellRounded - // compares center-to-center, so pass in the middle coordinates - pointToCellRounded(originX + (mCellWidth / 2), originY + (mCellHeight / 2), result); + // pointToCellRounded takes the top left of a cell but will pad that with + // cellWidth/2 and cellHeight/2 when finding the matching cell + pointToCellRounded(originX, originY, result); // If the item isn't fully on this screen, snap to the edges int rightOverhang = result[0] + spanX - countX; @@ -798,6 +823,7 @@ public class CellLayout extends ViewGroup { mDragCell[0] = -1; mDragCell[1] = -1; + setHover(false); mDragRect.setEmpty(); invalidate(); } @@ -1104,12 +1130,12 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { private int mCountX; private int mCountY; View cell; - int cellX; - int cellY; + int cellX = -1; + int cellY = -1; // intersectX and intersectY constrain the results of findCellForSpan; any empty space // it results must include this point (unless intersectX and intersectY are -1) - int intersectX; - int intersectY; + int intersectX = -1; + int intersectY = -1; int spanX; int spanY; int screen; @@ -1179,7 +1205,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { endY = Math.min(endY, intersectY + (spanY - 1)); } - for (int x = startX; x < endX + 1; x++) { + for (int x = startX; x < endX; x++) { inner: for (int y = startY; y < endY; y++) { for (int i = 0; i < spanX; i++) { diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java index 4a955b2..ef619be 100644 --- a/src/com/android/launcher2/CustomizePagedView.java +++ b/src/com/android/launcher2/CustomizePagedView.java @@ -166,12 +166,26 @@ public class CustomizePagedView extends PagedView final View animView = v; switch (mCustomizationType) { case WidgetCustomization: + // We assume that the view v is a TextView with a compound drawable on top, and that the + // whole text view is centered horizontally and top aligned. We get a more precise + // drag point using this information + final TextView textView = (TextView) animView; + final Drawable[] drawables = textView.getCompoundDrawables(); + final Drawable icon = drawables[1]; + int dragPointOffsetX = 0; + int dragPointOffsetY = 0; + Rect bounds = null; + if (icon != null) { + bounds = icon.getBounds(); + bounds.left = (v.getWidth() - bounds.right) / 2; + bounds.right += bounds.left; + } + AppWidgetProviderInfo appWidgetInfo = (AppWidgetProviderInfo) v.getTag(); LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(appWidgetInfo.provider); dragInfo.minWidth = appWidgetInfo.minWidth; dragInfo.minHeight = appWidgetInfo.minHeight; - mDragController.startDrag(v, this, dragInfo, DragController.DRAG_ACTION_COPY); - mLauncher.hideCustomizationDrawer(); + mDragController.startDrag(v, this, dragInfo, DragController.DRAG_ACTION_COPY, bounds); return true; case FolderCustomization: // animate some feedback to the long press diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java index 651b6f0..e18470a 100644 --- a/src/com/android/launcher2/DragController.java +++ b/src/com/android/launcher2/DragController.java @@ -151,7 +151,7 @@ public class DragController { /** * Starts a drag. - * + * * @param v The view that is being dragged * @param source An object representing where the drag originated * @param dragInfo The data associated with the object that is being dragged @@ -159,6 +159,22 @@ public class DragController { * {@link #DRAG_ACTION_COPY} */ public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) { + startDrag(v, source, dragInfo, dragAction, null); + } + + /** + * Starts a drag. + * + * @param v The view that is being dragged + * @param source An object representing where the drag originated + * @param dragInfo The data associated with the object that is being dragged + * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or + * {@link #DRAG_ACTION_COPY} + * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. + * Makes dragging feel more precise, e.g. you can clip out a transparent border + */ + public void startDrag(View v, DragSource source, Object dragInfo, int dragAction, + Rect dragRegion) { mOriginator = v; Bitmap b = getViewBitmap(v); @@ -174,7 +190,7 @@ public class DragController { int screenY = loc[1]; startDrag(b, screenX, screenY, 0, 0, b.getWidth(), b.getHeight(), - source, dragInfo, dragAction); + source, dragInfo, dragAction, dragRegion); b.recycle(); @@ -185,7 +201,7 @@ public class DragController { /** * Starts a drag. - * + * * @param b The bitmap to display as the drag image. It will be re-scaled to the * enlarged size. * @param screenX The x position on screen of the left-top of the bitmap. @@ -202,6 +218,31 @@ public class DragController { public void startDrag(Bitmap b, int screenX, int screenY, int textureLeft, int textureTop, int textureWidth, int textureHeight, DragSource source, Object dragInfo, int dragAction) { + startDrag(b, screenX, screenY, textureLeft, textureTop, textureWidth, textureHeight, + source, dragInfo, dragAction, null); + } + + /** + * Starts a drag. + * + * @param b The bitmap to display as the drag image. It will be re-scaled to the + * enlarged size. + * @param screenX The x position on screen of the left-top of the bitmap. + * @param screenY The y position on screen of the left-top of the bitmap. + * @param textureLeft The left edge of the region inside b to use. + * @param textureTop The top edge of the region inside b to use. + * @param textureWidth The width of the region inside b to use. + * @param textureHeight The height of the region inside b to use. + * @param source An object representing where the drag originated + * @param dragInfo The data associated with the object that is being dragged + * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or + * {@link #DRAG_ACTION_COPY} + * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. + * Makes dragging feel more precise, e.g. you can clip out a transparent border + */ + public void startDrag(Bitmap b, int screenX, int screenY, + int textureLeft, int textureTop, int textureWidth, int textureHeight, + DragSource source, Object dragInfo, int dragAction, Rect dragRegion) { if (PROFILE_DRAWING_DURING_DRAG) { android.os.Debug.startMethodTracing("Launcher"); } @@ -220,8 +261,10 @@ public class DragController { int registrationX = ((int)mMotionDownX) - screenX; int registrationY = ((int)mMotionDownY) - screenY; - mTouchOffsetX = mMotionDownX - screenX; - mTouchOffsetY = mMotionDownY - screenY; + final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left; + final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top; + mTouchOffsetX = mMotionDownX - screenX - dragRegionLeft; + mTouchOffsetY = mMotionDownY - screenY - dragRegionTop; mDragging = true; mDragSource = source; @@ -231,6 +274,12 @@ public class DragController { DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY, textureLeft, textureTop, textureWidth, textureHeight); + + if (dragRegion != null) { + dragView.setDragRegion(dragRegionLeft, dragRegion.top, + dragRegion.right - dragRegionLeft, dragRegion.bottom - dragRegionTop); + } + dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY); } diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java index bae592c..41e76f0 100644 --- a/src/com/android/launcher2/DragView.java +++ b/src/com/android/launcher2/DragView.java @@ -39,6 +39,11 @@ public class DragView extends View implements TweenCallback { private int mRegistrationX; private int mRegistrationY; + private int mDragRegionLeft = 0; + private int mDragRegionTop = 0; + private int mDragRegionWidth; + private int mDragRegionHeight; + SymmetricalLinearTween mTween; private float mScale; private float mAnimationScale = 1.0f; @@ -71,12 +76,37 @@ public class DragView extends View implements TweenCallback { scale.setScale(scaleFactor, scaleFactor); mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true); + mDragRegionWidth = width; + mDragRegionHeight = height; // The point in our scaled bitmap that the touch events are located mRegistrationX = registrationX + (DRAG_SCALE / 2); mRegistrationY = registrationY + (DRAG_SCALE / 2); } + public void setDragRegion(int left, int top, int width, int height) { + mDragRegionLeft = left; + mDragRegionTop = top; + mDragRegionWidth = width; + mDragRegionHeight = height; + } + + public int getDragRegionLeft() { + return mDragRegionLeft; + } + + public int getDragRegionTop() { + return mDragRegionTop; + } + + public int getDragRegionWidth() { + return mDragRegionWidth; + } + + public int getDragRegionHeight() { + return mDragRegionHeight; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight()); diff --git a/src/com/android/launcher2/FolderListAdapter.java b/src/com/android/launcher2/FolderListAdapter.java deleted file mode 100644 index ebb3332..0000000 --- a/src/com/android/launcher2/FolderListAdapter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher2; - -import com.android.launcher.R; - -import android.content.Context; -import android.content.pm.ResolveInfo; - -public class FolderListAdapter extends IntentListAdapter { - - public FolderListAdapter(Context context, String actionFilter) { - super(context, actionFilter); - - // Manually create a separate entry for creating a folder in Launcher - ResolveInfo folder = new ResolveInfo(); - folder.icon = R.drawable.ic_launcher_folder; - folder.labelRes = R.string.group_folder; - folder.resolvePackageName = context.getPackageName(); - mIntentList.add(0, folder); - } -} diff --git a/src/com/android/launcher2/IntentListAdapter.java b/src/com/android/launcher2/IntentListAdapter.java deleted file mode 100644 index f844738..0000000 --- a/src/com/android/launcher2/IntentListAdapter.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher2; - -import com.android.launcher.R; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Drawable; -import android.provider.LiveFolders; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.util.List; - -public class IntentListAdapter extends BaseAdapter { - private LayoutInflater mLayoutInflater; - private PackageManager mPackageManager; - protected List<ResolveInfo> mIntentList; - - public IntentListAdapter(Context context, String actionFilter) { - mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mPackageManager = context.getPackageManager(); - - Intent createLiveFolderIntent = new Intent(actionFilter); - mIntentList = mPackageManager.queryIntentActivities(createLiveFolderIntent, 0); - } - - public int getCount() { - return mIntentList.size(); - } - - public Object getItem(int position) { - return mIntentList.get(position); - } - - public long getItemId(int position) { - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - TextView textView; - - if (convertView == null) { - textView = (TextView) mLayoutInflater.inflate( - R.layout.home_customization_drawer_item, parent, false); - } else { - textView = (TextView) convertView; - } - - ResolveInfo info = mIntentList.get(position); - Drawable image = info.loadIcon(mPackageManager); - image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight()); - textView.setCompoundDrawables(null, image, null, null); - - CharSequence label = info.loadLabel(mPackageManager); - textView.setText(label); - - return textView; - } -} diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index c4bb69e..ee70b5e 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -205,6 +205,7 @@ public final class Launcher extends Activity private LauncherAppWidgetHost mAppWidgetHost; private CellLayout.CellInfo mAddItemCellInfo; + private int[] mAddItemCoordinates; private CellLayout.CellInfo mMenuAddInfo; private final int[] mCellCoordinates = new int[2]; private FolderInfo mFolderInfo; @@ -791,6 +792,7 @@ public final class Launcher extends Activity final int addScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1); if (addScreen > -1) { + mAddItemCoordinates = null; mAddItemCellInfo = new CellLayout.CellInfo(); final CellLayout.CellInfo addItemCellInfo = mAddItemCellInfo; addItemCellInfo.valid = true; @@ -818,7 +820,7 @@ public final class Launcher extends Activity * Finds all the views we need and configure them properly. */ private void setupViews() { - DragController dragController = mDragController; + final DragController dragController = mDragController; DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer); dragLayer.setDragController(dragController); @@ -1040,8 +1042,26 @@ public final class Launcher extends Activity int[] spans = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight, null); // Try finding open space on Launcher screen + // We have saved the position to which the widget was dragged-- this really only matters + // if we are placing widgets on a "spring-loaded" screen final int[] xy = mCellCoordinates; - if (!findSlot(cellInfo, xy, spans[0], spans[1])) { + + // For now, we don't save the coordinate where we dropped the icon because we're not + // supporting spring-loaded mini-screens; however, leaving the ability to directly place + // a widget on the home screen in case we want to add it in the future + final int[] xyTouch = null; + //final int[] xyTouch = mAddItemCoordinates; + boolean findNearestVacantAreaFailed = false; + if (xyTouch != null) { + CellLayout screen = (CellLayout) mWorkspace.getChildAt(cellInfo.screen); + int[] result = screen.findNearestVacantArea( + mAddItemCoordinates[0], mAddItemCoordinates[1], + spans[0], spans[1], cellInfo, xy); + findNearestVacantAreaFailed = (result == null); + } + + if (findNearestVacantAreaFailed || + (xyTouch == null && !findSlot(cellInfo, xy, spans[0], spans[1]))) { if (appWidgetId != -1) mAppWidgetHost.deleteAppWidgetId(appWidgetId); return; } @@ -1053,7 +1073,7 @@ public final class Launcher extends Activity LauncherModel.addItemToDatabase(this, launcherInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, - mWorkspace.getCurrentScreen(), xy[0], xy[1], false); + cellInfo.screen, xy[0], xy[1], false); if (!mRestoring) { mDesktopItems.add(launcherInfo); @@ -1064,7 +1084,7 @@ public final class Launcher extends Activity launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo); launcherInfo.hostView.setTag(launcherInfo); - mWorkspace.addInCurrentScreen(launcherInfo.hostView, xy[0], xy[1], + mWorkspace.addInScreen(launcherInfo.hostView, cellInfo.screen, xy[0], xy[1], launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked()); } } @@ -1307,7 +1327,7 @@ public final class Launcher extends Activity // Disable add if the workspace is full. if (visible) { - mMenuAddInfo = mWorkspace.updateOccupiedCells(null); + mMenuAddInfo = mWorkspace.updateOccupiedCellsForCurrentScreen(null); menu.setGroupEnabled(MENU_GROUP_ADD, mMenuAddInfo != null && mMenuAddInfo.valid); } @@ -1317,8 +1337,9 @@ public final class Launcher extends Activity // we need to initialize mAddItemCellInfo before adding something to the homescreen -- when // using the settings menu to add an item, something similar happens in showAddDialog public void prepareAddItemFromHomeCustomizationDrawer() { - mMenuAddInfo = mWorkspace.updateOccupiedCells(null); + mMenuAddInfo = mWorkspace.updateOccupiedCellsForCurrentScreen(null); mAddItemCellInfo = mMenuAddInfo; + mAddItemCellInfo = null; } @Override @@ -1369,8 +1390,12 @@ public final class Launcher extends Activity } } - void addAppWidgetFromDrop(ComponentName appWidgetProvider, CellLayout.CellInfo cellInfo) { + void addAppWidgetFromDrop(ComponentName appWidgetProvider, CellLayout.CellInfo cellInfo, + int[] position) { mAddItemCellInfo = cellInfo; + + // only set mAddItemCoordinates if we dropped on home screen in "spring-loaded" manner + mAddItemCoordinates = position; int appWidgetId = getAppWidgetHost().allocateAppWidgetId(); AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, appWidgetProvider); addAppWidgetImpl(appWidgetId); @@ -1523,9 +1548,8 @@ public final class Launcher extends Activity private boolean findSlot(CellLayout.CellInfo cellInfo, int[] xy, int spanX, int spanY) { if (!cellInfo.findCellForSpan(xy, spanX, spanY)) { - boolean[] occupied = mSavedState != null ? - mSavedState.getBooleanArray(RUNTIME_STATE_PENDING_ADD_OCCUPIED_CELLS) : null; - cellInfo = mWorkspace.updateOccupiedCells(occupied); + CellLayout targetLayout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen); + cellInfo = targetLayout.updateOccupiedCells(null, null); if (!cellInfo.findCellForSpan(xy, spanX, spanY)) { Toast.makeText(this, getString(R.string.out_of_space), Toast.LENGTH_SHORT).show(); return false; @@ -2034,6 +2058,7 @@ public final class Launcher extends Activity private void showAddDialog(CellLayout.CellInfo cellInfo) { mAddItemCellInfo = cellInfo; + mAddItemCoordinates = null; mWaitingForResult = true; showDialog(DIALOG_CREATE_SHORTCUT); } diff --git a/src/com/android/launcher2/WidgetListAdapter.java b/src/com/android/launcher2/WidgetListAdapter.java deleted file mode 100644 index 61e7c89..0000000 --- a/src/com/android/launcher2/WidgetListAdapter.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher2; - -import com.android.launcher.R; - -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProviderInfo; -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.Region.Op; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.TextView; - -import java.util.List; - -public class WidgetListAdapter extends BaseAdapter { - private final Launcher mLauncher; - private List<AppWidgetProviderInfo> mWidgets; - private final Canvas mCanvas = new Canvas(); - - private final int[] mTempSize = new int[2]; - private final Rect mTempRect = new Rect(); - - private static final String TAG = "Launcher.WidgetGalleryAdapter"; - - WidgetListAdapter(Launcher launcher) { - mLauncher = launcher; - mWidgets = AppWidgetManager.getInstance(launcher).getInstalledProviders(); - } - - public int getCount() { - return mWidgets.size(); - } - - public Object getItem(int position) { - return mWidgets.get(position); - } - - public long getItemId(int position) { - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - TextView textView; - - if (convertView == null) { - LayoutInflater inflater = - (LayoutInflater)mLauncher.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - textView = (TextView) inflater.inflate( - R.layout.home_customization_drawer_widget, parent, false); - } else { - textView = (TextView) convertView; - } - - AppWidgetProviderInfo info = mWidgets.get(position); - PackageManager packageManager = mLauncher.getPackageManager(); - String packageName = info.provider.getPackageName(); - Drawable drawable = null; - if (info.previewImage != 0) { - drawable = packageManager.getDrawable(packageName, info.previewImage, null); - if (drawable == null) { - Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) - + " for provider: " + info.provider); - } - } - // If we don't have a preview image, create a default one - if (drawable == null) { - Resources resources = mLauncher.getResources(); - - // Determine the size the widget will take in the layout - mLauncher.getWorkspace().estimateChildSize(info.minWidth, info.minHeight, mTempSize); - - // Create a new bitmap to hold the widget preview - final int width = mTempSize[0]; - final int height = mTempSize[1]; - Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); - mCanvas.setBitmap(bitmap); - // For some reason, we must re-set the clip rect here, otherwise it will be wrong - mCanvas.clipRect(0, 0, width, height, Op.REPLACE); - - Drawable background = resources.getDrawable(R.drawable.default_widget_preview); - background.setBounds(0, 0, width, height); - background.draw(mCanvas); - - // Draw the icon vertically centered, flush left - try { - Drawable icon = packageManager.getDrawable(packageName, info.icon, null); - background.getPadding(mTempRect); - - final int left = mTempRect.left; - final int top = (height - icon.getIntrinsicHeight()) / 2; - icon.setBounds( - left, top, left + icon.getIntrinsicWidth(), top + icon.getIntrinsicHeight()); - icon.draw(mCanvas); - } catch (Resources.NotFoundException e) { - // if we can't find the icon, then just don't draw it - } - - drawable = new BitmapDrawable(resources, bitmap); - } - drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); - textView.setCompoundDrawables(null, drawable, null, null); - textView.setText(info.label); - // Store the widget info on the associated view so we can easily fetch it later - textView.setTag(info); - - return textView; - } -} diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 73eaeab..fc505c7 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -34,6 +34,7 @@ import android.content.pm.ProviderInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -124,6 +125,8 @@ public class Workspace extends ViewGroup private int[] mTempCell = new int[2]; private int[] mTempEstimate = new int[2]; + private float[] mTempDragCoordinates = new float[2]; + private float[] mTempDragBottomRightCoordinates = new float[2]; private boolean mAllowLongPress = true; @@ -459,7 +462,7 @@ public class Workspace extends ViewGroup } } - CellLayout.CellInfo updateOccupiedCells(boolean[] occupied) { + CellLayout.CellInfo updateOccupiedCellsForCurrentScreen(boolean[] occupied) { CellLayout group = (CellLayout) getChildAt(mCurrentScreen); if (group != null) { return group.updateOccupiedCells(occupied, null); @@ -1309,9 +1312,31 @@ public class Workspace extends ViewGroup public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { - final CellLayout cellLayout = getCurrentDropLayout(); + CellLayout cellLayout = getCurrentDropLayout(); + int originX = x - xOffset; + int originY = y - yOffset; + if (mIsSmall) { + // find out which target layout is over + final float[] localXY = mTempDragCoordinates; + localXY[0] = originX; + localXY[1] = originY; + final float[] localBottomRightXY = mTempDragBottomRightCoordinates; + // we need to subtract left/top here because DragController already adds + // dragRegionLeft/Top to xOffset and yOffset + localBottomRightXY[0] = originX + dragView.getDragRegionWidth(); + localBottomRightXY[1] = originY + dragView.getDragRegionHeight(); + cellLayout = findMatchingScreenForDragOver(localXY, localBottomRightXY); + if (cellLayout == null) { + // cancel the drag if we're not over a mini-screen at time of drop + // TODO: maybe add a nice fade here? + return; + } + // localXY will be transformed into the local screen's coordinate space; save that info + originX = (int)localXY[0]; + originY = (int)localXY[1]; + } if (source != this) { - onDropExternal(x - xOffset, y - yOffset, dragInfo, cellLayout); + onDropExternal(originX, originY, dragInfo, cellLayout); } else { // Move internally if (mDragInfo != null) { @@ -1323,7 +1348,8 @@ public class Workspace extends ViewGroup addInScreen(cell, index, mDragInfo.cellX, mDragInfo.cellY, mDragInfo.spanX, mDragInfo.spanY); } - mTargetCell = estimateDropCell(x - xOffset, y - yOffset, + + mTargetCell = estimateDropCell(originX, originY, mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout, mTargetCell); cellLayout.onDropChild(cell); @@ -1381,11 +1407,87 @@ public class Workspace extends ViewGroup return null; } + // xy = upper left corner of item being dragged + // bottomRightXy = lower right corner of item being dragged + // This method will see which mini-screen is most overlapped by the item being dragged, and + // return it. It will also transform the parameters xy and bottomRightXy into the local + // coordinate space of the returned screen + private CellLayout findMatchingScreenForDragOver(float[] xy, float[] bottomRightXy) { + float x = xy[0]; + float y = xy[1]; + float right = bottomRightXy[0]; + float bottom = bottomRightXy[1]; + + float bestX = 0; + float bestY = 0; + float bestRight = 0; + float bestBottom = 0; + + Matrix inverseMatrix = new Matrix(); + + // We loop through all the screens (ie CellLayouts) and see which one overlaps the most + // with the item being dragged. + final int screenCount = getChildCount(); + CellLayout bestMatchingScreen = null; + float bestOverlapSoFar = 0; + for (int i = 0; i < screenCount; i++) { + CellLayout cl = (CellLayout)getChildAt(i); + // Transform the coordinates of the item being dragged to the CellLayout's coordinates + float left = cl.getLeft(); + float top = cl.getTop(); + xy[0] = x + mScrollX - left; + xy[1] = y + mScrollY - top; + cl.getMatrix().invert(inverseMatrix); + + bottomRightXy[0] = right + mScrollX - left; + bottomRightXy[1] = bottom + mScrollY - top; + + inverseMatrix.mapPoints(xy); + inverseMatrix.mapPoints(bottomRightXy); + + float dragRegionX = xy[0]; + float dragRegionY = xy[1]; + float dragRegionRight = bottomRightXy[0]; + float dragRegionBottom = bottomRightXy[1]; + + // Find the overlapping region + float overlapLeft = Math.max(0f, dragRegionX); + float overlapTop = Math.max(0f, dragRegionY); + float overlapBottom = Math.min(cl.getHeight(), dragRegionBottom); + float overlapRight = Math.min(cl.getWidth(), dragRegionRight); + + if (overlapRight >= 0 && overlapLeft <= cl.getWidth() && + overlapTop >= 0 && overlapBottom <= cl.getHeight()) { + // Calculate the size of the overlapping region + float overlap = (overlapRight - overlapLeft) * (overlapBottom - overlapTop); + if (overlap > bestOverlapSoFar) { + bestOverlapSoFar = overlap; + bestMatchingScreen = cl; + bestX = xy[0]; + bestY = xy[1]; + bestRight = bottomRightXy[0]; + bestBottom = bottomRightXy[1]; + } + } + } + if (bestMatchingScreen != null && bestMatchingScreen != mDragTargetLayout) { + if (mDragTargetLayout != null) { + mDragTargetLayout.onDragComplete(); + } + mDragTargetLayout = bestMatchingScreen; + } + xy[0] = bestX; + xy[1] = bestY; + bottomRightXy[0] = bestRight; + bottomRightXy[1] = bestBottom; + return bestMatchingScreen; + } + public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { final ItemInfo item = (ItemInfo)dragInfo; - final CellLayout currentLayout = getCurrentDropLayout(); + CellLayout currentLayout = getCurrentDropLayout(); if (dragInfo instanceof LauncherAppWidgetInfo) { LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo; @@ -1397,6 +1499,39 @@ public class Workspace extends ViewGroup item.spanY = spans[1]; } } + int originX = x - xOffset; + int originY = y - yOffset; + if (mIsSmall) { + // find out which mini screen the dragged item is over + final float[] localXY = mTempDragCoordinates; + localXY[0] = originX; + localXY[1] = originY; + final float[] localBottomRightXY = mTempDragBottomRightCoordinates; + + localBottomRightXY[0] = originX + dragView.getDragRegionWidth(); + localBottomRightXY[1] = originY + dragView.getDragRegionHeight(); + currentLayout = findMatchingScreenForDragOver(localXY, localBottomRightXY); + if (currentLayout != null) { + currentLayout.setHover(true); + } + + originX = (int)localXY[0]; + originY = (int)localXY[1]; + } + + if (source != this) { + // This is a hack to fix the point used to determine which cell an icon from the all + // apps screen is over + if (item != null && item.spanX == 1 && currentLayout != null) { + int dragRegionLeft = (dragView.getWidth() - currentLayout.getCellWidth()) / 2; + + originX += dragRegionLeft - dragView.getDragRegionLeft(); + if (dragView.getDragRegionWidth() != currentLayout.getCellWidth()) { + dragView.setDragRegion(dragView.getDragRegionLeft(), dragView.getDragRegionTop(), + currentLayout.getCellWidth(), dragView.getDragRegionHeight()); + } + } + } if (currentLayout != mDragTargetLayout) { if (mDragTargetLayout != null) { mDragTargetLayout.onDragComplete(); @@ -1404,23 +1539,14 @@ public class Workspace extends ViewGroup mDragTargetLayout = currentLayout; } - // Find the top left corner of the item - int originX = x - xOffset; - int originY = y - yOffset; - - // If not dragging from the Workspace, the size of dragView might not match the cell size - if (!source.equals(this)) { - // Break the drag view up into evenly sized chunks based on its spans - int chunkWidth = dragView.getWidth() / item.spanX; - int chunkHeight = dragView.getHeight() / item.spanY; - - // Adjust the origin for a cell centered at the top left chunk - originX += (chunkWidth - currentLayout.getCellWidth()) / 2; - originY += (chunkHeight - currentLayout.getCellHeight()) / 2; + // only visualize the drop locations for moving icons within the home screen on tablet + // on phone, we also visualize icons dragged in from All Apps + if ((!LauncherApplication.isScreenXLarge() || source == this) + && mDragTargetLayout != null) { + final View child = (mDragInfo == null) ? null : mDragInfo.cell; + mDragTargetLayout.visualizeDropLocation( + child, originX, originY, item.spanX, item.spanY); } - - final View child = (mDragInfo == null) ? null : mDragInfo.cell; - currentLayout.visualizeDropLocation(child, originX, originY, item.spanX, item.spanY); } public void onDragExit(DragSource source, int x, int y, int xOffset, @@ -1460,7 +1586,11 @@ public class Workspace extends ViewGroup break; case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: cellLayout.setTagToCellInfoForPoint(x, y); - mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName, cellLayout.getTag()); + int[] position = new int[2]; + position[0] = x; + position[1] = y; + mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName, + cellLayout.getTag(), position); break; default: throw new IllegalStateException("Unknown item type: " |