From af44209bfa60da3c7ab49b7f508f9effd316ee41 Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Thu, 10 Jun 2010 17:01:57 -0700 Subject: First cut at new home screen customization for xlarge displays. - Add new layout for xlarge, removing hotseat, next/prev page, etc. - Add a "+" button in top right which switches to customization mode - Add a widget chooser which slides up from bottom of screen - Initial support for dragging widgets onto home screen Change-Id: I14e2e013ccceff4066fcb7c4492b4f6bef6595e7 --- src/com/android/launcher2/CellLayout.java | 103 ++++++++-------- src/com/android/launcher2/Launcher.java | 137 ++++++++++++++------- .../android/launcher2/LauncherAppWidgetInfo.java | 2 + src/com/android/launcher2/WidgetChooser.java | 94 ++++++++++++++ .../android/launcher2/WidgetGalleryAdapter.java | 73 +++++++++++ src/com/android/launcher2/Workspace.java | 46 ++++--- 6 files changed, 344 insertions(+), 111 deletions(-) create mode 100644 src/com/android/launcher2/WidgetChooser.java create mode 100644 src/com/android/launcher2/WidgetGalleryAdapter.java (limited to 'src') diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 56b62ba91..73481c248 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -158,67 +158,72 @@ public class CellLayout extends ViewGroup { mCellInfo.screen = ((ViewGroup) getParent()).indexOfChild(this); } - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - final int action = ev.getAction(); + public void setTagToCellInfoForPoint(int touchX, int touchY) { final CellInfo cellInfo = mCellInfo; + final Rect frame = mRect; + final int x = touchX + mScrollX; + final int y = touchY + mScrollY; + final int count = getChildCount(); - if (action == MotionEvent.ACTION_DOWN) { - final Rect frame = mRect; - final int x = (int) ev.getX() + mScrollX; - final int y = (int) ev.getY() + mScrollY; - final int count = getChildCount(); + boolean found = false; + for (int i = count - 1; i >= 0; i--) { + final View child = getChildAt(i); - boolean found = false; - for (int i = count - 1; i >= 0; i--) { - final View child = getChildAt(i); - - if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) { - child.getHitRect(frame); - if (frame.contains(x, y)) { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - cellInfo.cell = child; - cellInfo.cellX = lp.cellX; - cellInfo.cellY = lp.cellY; - cellInfo.spanX = lp.cellHSpan; - cellInfo.spanY = lp.cellVSpan; - cellInfo.valid = true; - found = true; - mDirtyTag = false; - break; - } + if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) { + child.getHitRect(frame); + if (frame.contains(x, y)) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + cellInfo.cell = child; + cellInfo.cellX = lp.cellX; + cellInfo.cellY = lp.cellY; + cellInfo.spanX = lp.cellHSpan; + cellInfo.spanY = lp.cellVSpan; + cellInfo.valid = true; + found = true; + mDirtyTag = false; + break; } } + } - mLastDownOnOccupiedCell = found; + mLastDownOnOccupiedCell = found; - if (!found) { - int cellXY[] = mCellXY; - pointToCellExact(x, y, cellXY); + if (!found) { + int cellXY[] = mCellXY; + pointToCellExact(x, y, cellXY); - final boolean portrait = mPortrait; - final int xCount = portrait ? mShortAxisCells : mLongAxisCells; - final int yCount = portrait ? mLongAxisCells : mShortAxisCells; + final boolean portrait = mPortrait; + final int xCount = portrait ? mShortAxisCells : mLongAxisCells; + final int yCount = portrait ? mLongAxisCells : mShortAxisCells; - final boolean[][] occupied = mOccupied; - findOccupiedCells(xCount, yCount, occupied, null); + final boolean[][] occupied = mOccupied; + findOccupiedCells(xCount, yCount, occupied, null); - cellInfo.cell = null; - cellInfo.cellX = cellXY[0]; - cellInfo.cellY = cellXY[1]; - cellInfo.spanX = 1; - cellInfo.spanY = 1; - cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < xCount && - cellXY[1] < yCount && !occupied[cellXY[0]][cellXY[1]]; + cellInfo.cell = null; + cellInfo.cellX = cellXY[0]; + cellInfo.cellY = cellXY[1]; + cellInfo.spanX = 1; + cellInfo.spanY = 1; + cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < xCount && + cellXY[1] < yCount && !occupied[cellXY[0]][cellXY[1]]; + + // Instead of finding the interesting vacant cells here, wait until a + // caller invokes getTag() to retrieve the result. Finding the vacant + // cells is a bit expensive and can generate many new objects, it's + // therefore better to defer it until we know we actually need it. + + mDirtyTag = true; + } + setTag(cellInfo); + } - // Instead of finding the interesting vacant cells here, wait until a - // caller invokes getTag() to retrieve the result. Finding the vacant - // cells is a bit expensive and can generate many new objects, it's - // therefore better to defer it until we know we actually need it. + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + final CellInfo cellInfo = mCellInfo; - mDirtyTag = true; - } - setTag(cellInfo); + if (action == MotionEvent.ACTION_DOWN) { + setTagToCellInfoForPoint((int) ev.getX(), (int) ev.getY()); } else if (action == MotionEvent.ACTION_UP) { cellInfo.cell = null; cellInfo.cellX = -1; diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index a5988bf6c..07e8834c0 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -17,6 +17,7 @@ package com.android.launcher2; import com.android.common.Search; +import com.android.launcher.R; import android.app.Activity; import android.app.AlertDialog; @@ -24,6 +25,8 @@ import android.app.Dialog; import android.app.SearchManager; import android.app.StatusBarManager; import android.app.WallpaperManager; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -31,9 +34,8 @@ import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.Intent.ShortcutIconResource; import android.content.IntentFilter; -import android.content.pm.ActivityInfo; +import android.content.Intent.ShortcutIconResource; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; @@ -41,10 +43,10 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.Bitmap; -import android.graphics.Rect; import android.graphics.Canvas; -import android.graphics.drawable.Drawable; +import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -66,25 +68,22 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.View.OnLongClickListener; +import android.view.animation.AnimationUtils; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; import android.widget.ImageView; -import android.widget.PopupWindow; import android.widget.LinearLayout; -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProviderInfo; +import android.widget.PopupWindow; +import android.widget.TextView; +import android.widget.Toast; -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; +import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.DataInputStream; - -import com.android.launcher.R; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; /** * Default launcher application. @@ -182,6 +181,7 @@ public final class Launcher extends Activity private DeleteZone mDeleteZone; private HandleView mHandleView; private AllAppsView mAllAppsGrid; + private WidgetChooser mWidgetChooser; private Bundle mSavedState; @@ -536,10 +536,13 @@ public final class Launcher extends Activity completeAddLiveFolder(data, mAddItemCellInfo); break; case REQUEST_PICK_APPWIDGET: - addAppWidget(data); + addAppWidgetFromPick(data); break; case REQUEST_CREATE_APPWIDGET: - completeAddAppWidget(data, mAddItemCellInfo); + int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); + // TODO: Is this log message meaningful? + if (LOGD) Log.d(TAG, "dumping extras content=" + data.getExtras()); + completeAddAppWidget(appWidgetId, mAddItemCellInfo); break; case REQUEST_PICK_WALLPAPER: // We just wanted the activity result here so we can clear mWaitingForResult @@ -572,8 +575,11 @@ public final class Launcher extends Activity @Override protected void onPause() { super.onPause(); - dismissPreview(mPreviousView); - dismissPreview(mNextView); + // Some launcher layouts don't have a previous and next view + if (mPreviousView != null) { + dismissPreview(mPreviousView); + dismissPreview(mNextView); + } mDragController.cancelDrag(); } @@ -720,24 +726,30 @@ public final class Launcher extends Activity mHandleView.setOnClickListener(this); mHandleView.setOnLongClickListener(this); - ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left); - hotseatLeft.setContentDescription(mHotseatLabels[0]); - hotseatLeft.setImageDrawable(mHotseatIcons[0]); - ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right); - hotseatRight.setContentDescription(mHotseatLabels[1]); - hotseatRight.setImageDrawable(mHotseatIcons[1]); + mWidgetChooser = (WidgetChooser) findViewById(R.id.widget_chooser); + if (mWidgetChooser != null) { + mWidgetChooser.setDragController(dragController); + mWidgetChooser.setLauncher(this); + } else { + ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left); + hotseatLeft.setContentDescription(mHotseatLabels[0]); + hotseatLeft.setImageDrawable(mHotseatIcons[0]); + ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right); + hotseatRight.setContentDescription(mHotseatLabels[1]); + hotseatRight.setImageDrawable(mHotseatIcons[1]); - mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen); - mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen); + mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen); + mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen); - Drawable previous = mPreviousView.getDrawable(); - Drawable next = mNextView.getDrawable(); - mWorkspace.setIndicators(previous, next); + Drawable previous = mPreviousView.getDrawable(); + Drawable next = mNextView.getDrawable(); + mWorkspace.setIndicators(previous, next); - mPreviousView.setHapticFeedbackEnabled(false); - mPreviousView.setOnLongClickListener(this); - mNextView.setHapticFeedbackEnabled(false); - mNextView.setOnLongClickListener(this); + mPreviousView.setHapticFeedbackEnabled(false); + mPreviousView.setOnLongClickListener(this); + mNextView.setHapticFeedbackEnabled(false); + mNextView.setOnLongClickListener(this); + } workspace.setOnLongClickListener(this); workspace.setDragController(dragController); @@ -745,7 +757,8 @@ public final class Launcher extends Activity deleteZone.setLauncher(this); deleteZone.setDragController(dragController); - deleteZone.setHandle(findViewById(R.id.all_apps_button_cluster)); + int deleteZoneHandleId = isScreenXLarge() ? R.id.add_button : R.id.all_apps_button_cluster; + deleteZone.setHandle(findViewById(deleteZoneHandleId)); dragController.setDragScoller(workspace); dragController.setDragListener(deleteZone); @@ -876,12 +889,7 @@ public final class Launcher extends Activity * @param data The intent describing the appWidgetId. * @param cellInfo The position on screen where to create the widget. */ - private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) { - Bundle extras = data.getExtras(); - int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); - - if (LOGD) Log.d(TAG, "dumping extras content=" + extras.toString()); - + private void completeAddAppWidget(int appWidgetId, CellLayout.CellInfo cellInfo) { AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId); // Calculate the grid spans needed to fit this widget @@ -1171,9 +1179,27 @@ public final class Launcher extends Activity showAddDialog(mMenuAddInfo); } - void addAppWidget(Intent data) { + boolean isScreenXLarge() { + int screenLayout = getResources().getConfiguration().screenLayout; + return (screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; + } + + void addAppWidgetFromDrop(ComponentName appWidgetProvider, CellLayout.CellInfo cellInfo) { + mAddItemCellInfo = cellInfo; + int appWidgetId = getAppWidgetHost().allocateAppWidgetId(); + AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, appWidgetProvider); + addAppWidgetImpl(appWidgetId); + } + + void addAppWidgetFromPick(Intent data) { // TODO: catch bad widget exception when sent int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); + // TODO: Is this log message meaningful? + if (LOGD) Log.d(TAG, "dumping extras content=" + data.getExtras()); + addAppWidgetImpl(appWidgetId); + } + + void addAppWidgetImpl(int appWidgetId) { AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); if (appWidget.configure != null) { @@ -1185,7 +1211,7 @@ public final class Launcher extends Activity startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET); } else { // Otherwise just add it - onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); + completeAddAppWidget(appWidgetId, mAddItemCellInfo); } } @@ -1389,8 +1415,11 @@ public final class Launcher extends Activity } else { closeFolder(); } - dismissPreview(mPreviousView); - dismissPreview(mNextView); + // Some launcher layouts don't have a previous and next view + if (mPreviousView != null) { + dismissPreview(mPreviousView); + dismissPreview(mNextView); + } } private void closeFolder() { @@ -1456,6 +1485,24 @@ public final class Launcher extends Activity } } + /** + * Event handler for the "plus" button that appears on the home screen, which + * enters home screen customization mode. + * + * @param v The view that was clicked. + */ + public void onClickAddButton(View v) { + View widgetChooser = findViewById(R.id.widget_chooser); + widgetChooser.setVisibility(View.VISIBLE); + + // Animate the widget chooser up from the bottom of the screen + widgetChooser.startAnimation(AnimationUtils.loadAnimation(this, R.anim.widget_chooser_slide_up)); + } + + public void onClickAllAppsButton(View w) { + showAllApps(true); + } + void startActivitySafely(Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { diff --git a/src/com/android/launcher2/LauncherAppWidgetInfo.java b/src/com/android/launcher2/LauncherAppWidgetInfo.java index 8499ebb7c..3c81bac8e 100644 --- a/src/com/android/launcher2/LauncherAppWidgetInfo.java +++ b/src/com/android/launcher2/LauncherAppWidgetInfo.java @@ -17,6 +17,7 @@ package com.android.launcher2; import android.appwidget.AppWidgetHostView; +import android.content.ComponentName; import android.content.ContentValues; /** @@ -29,6 +30,7 @@ class LauncherAppWidgetInfo extends ItemInfo { * {@link android.appwidget.AppWidgetManager} for updates. */ int appWidgetId; + ComponentName providerName; /** * View that holds this widget after it's been created. This view isn't created diff --git a/src/com/android/launcher2/WidgetChooser.java b/src/com/android/launcher2/WidgetChooser.java new file mode 100644 index 000000000..fc354d79a --- /dev/null +++ b/src/com/android/launcher2/WidgetChooser.java @@ -0,0 +1,94 @@ +package com.android.launcher2; + +import android.appwidget.AppWidgetProviderInfo; +import android.content.Context; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Gallery; + +public class WidgetChooser extends Gallery + implements Gallery.OnItemLongClickListener, DragSource { + + Context mContext; + + private Launcher mLauncher; + private DragController mDragController; + private WidgetGalleryAdapter mWidgetGalleryAdapter; + + private int mMotionDownRawX; + private int mMotionDownRawY; + + public WidgetChooser(Context context, AttributeSet attrs) { + super(context, attrs); + setLongClickable(true); + setOnItemLongClickListener(this); + mContext = context; + + setCallbackDuringFling(false); + + mWidgetGalleryAdapter = new WidgetGalleryAdapter(context); + setAdapter(mWidgetGalleryAdapter); + } + + public void onDropCompleted(View target, boolean success) { + // TODO Auto-generated method stub + + } + + public void setDragController(DragController dragger) { + mDragController = dragger; + } + + public void setLauncher(Launcher launcher) { + mLauncher = launcher; + } + + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + AppWidgetProviderInfo info = (AppWidgetProviderInfo)mWidgetGalleryAdapter.getItem(position); + try { + Resources r = mContext.getPackageManager().getResourcesForApplication(info.provider.getPackageName()); + + Bitmap bmp = BitmapFactory.decodeResource(r, info.icon); + final int w = bmp.getWidth(); + final int h = bmp.getHeight(); + + // We don't really have an accurate location to use. This will do. + int screenX = mMotionDownRawX - (w / 2); + int screenY = mMotionDownRawY - h; + + LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(-1); + dragInfo.providerName = info.provider; + mDragController.startDrag(bmp, screenX, screenY, + 0, 0, w, h, this, dragInfo, DragController.DRAG_ACTION_COPY); + return true; + } catch (NameNotFoundException e) { + return false; + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) { + return false; + } + + super.onTouchEvent(ev); + + int x = (int) ev.getX(); + int y = (int) ev.getY(); + + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + mMotionDownRawX = (int) ev.getRawX(); + mMotionDownRawY = (int) ev.getRawY(); + } + return true; + } +} diff --git a/src/com/android/launcher2/WidgetGalleryAdapter.java b/src/com/android/launcher2/WidgetGalleryAdapter.java new file mode 100644 index 000000000..d6272d45f --- /dev/null +++ b/src/com/android/launcher2/WidgetGalleryAdapter.java @@ -0,0 +1,73 @@ +/* + * 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.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; + +import java.util.List; + +public class WidgetGalleryAdapter extends BaseAdapter { + private LayoutInflater mLayoutInflater; + private PackageManager mPackageManager; + private List mWidgets; + + WidgetGalleryAdapter(Context context) { + mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + AppWidgetManager widgetManager = AppWidgetManager.getInstance(context); + mWidgets = widgetManager.getInstalledProviders(); + mPackageManager = context.getPackageManager(); + } + + 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) { + ImageView imageView; + + if (convertView == null) { + imageView = (ImageView) mLayoutInflater.inflate(R.layout.widget_item, parent, false); + } else { + imageView = (ImageView) convertView; + } + + AppWidgetProviderInfo info = mWidgets.get(position); + Drawable drawable = mPackageManager.getDrawable(info.provider.getPackageName(), info.icon, null); + imageView.setImageDrawable(drawable); + + return imageView; + } +} diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index c337c3078..c56a313e1 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -16,8 +16,7 @@ package com.android.launcher2; -import java.util.ArrayList; -import java.util.HashSet; +import com.android.launcher.R; import android.app.WallpaperManager; import android.appwidget.AppWidgetManager; @@ -47,7 +46,8 @@ import android.view.animation.Interpolator; import android.widget.Scroller; import android.widget.TextView; -import com.android.launcher.R; +import java.util.ArrayList; +import java.util.HashSet; /** * The workspace is a wide area with a wallpaper and a finite number of screens. Each @@ -450,8 +450,10 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag postInvalidate(); } else if (mNextScreen != INVALID_SCREEN) { mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1)); - mPreviousIndicator.setLevel(mCurrentScreen); - mNextIndicator.setLevel(mCurrentScreen); + if (mPreviousIndicator != null) { + mPreviousIndicator.setLevel(mCurrentScreen); + mNextIndicator.setLevel(mCurrentScreen); + } Launcher.setScreen(mCurrentScreen); mNextScreen = INVALID_SCREEN; clearChildrenCache(); @@ -963,8 +965,10 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag mNextScreen = whichScreen; + if (mPreviousIndicator != null) { mPreviousIndicator.setLevel(mNextScreen); mNextIndicator.setLevel(mNextScreen); + } View focusedChild = getFocusedChild(); if (focusedChild != null && whichScreen != mCurrentScreen && @@ -1098,7 +1102,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag // Drag from somewhere else ItemInfo info = (ItemInfo) dragInfo; - View view; + View view = null; switch (info.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: @@ -1113,23 +1117,31 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, (ViewGroup) getChildAt(mCurrentScreen), ((UserFolderInfo) info)); break; + case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: + cellLayout.setTagToCellInfoForPoint(x, y); + mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName, cellLayout.getTag()); + break; default: throw new IllegalStateException("Unknown item type: " + info.itemType); } - cellLayout.addView(view, insertAtFirst ? 0 : -1); - view.setHapticFeedbackEnabled(false); - view.setOnLongClickListener(mLongClickListener); - if (view instanceof DropTarget) { - mDragController.addDropTarget((DropTarget) view); - } + // addAppWidgetFromDrop already took care of attaching the widget view to the appropriate cell + // TODO why aren't we calling addInScreen here? + if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) { + cellLayout.addView(view, insertAtFirst ? 0 : -1); + view.setHapticFeedbackEnabled(false); + view.setOnLongClickListener(mLongClickListener); + if (view instanceof DropTarget) { + mDragController.addDropTarget((DropTarget) view); + } - mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell); - cellLayout.onDropChild(view, mTargetCell); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); + mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell); + cellLayout.onDropChild(view, mTargetCell); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); - LauncherModel.addOrMoveItemInDatabase(mLauncher, info, - LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY); + LauncherModel.addOrMoveItemInDatabase(mLauncher, info, + LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY); + } } /** -- cgit v1.2.3