summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/anim/widget_chooser_slide_up.xml23
-rw-r--r--res/drawable/add_button.pngbin0 -> 2372 bytes
-rw-r--r--res/layout-xlarge/launcher.xml92
-rw-r--r--res/layout/widget_item.xml22
-rw-r--r--src/com/android/launcher2/CellLayout.java103
-rw-r--r--src/com/android/launcher2/Launcher.java137
-rw-r--r--src/com/android/launcher2/LauncherAppWidgetInfo.java2
-rw-r--r--src/com/android/launcher2/WidgetChooser.java94
-rw-r--r--src/com/android/launcher2/WidgetGalleryAdapter.java73
-rw-r--r--src/com/android/launcher2/Workspace.java46
10 files changed, 481 insertions, 111 deletions
diff --git a/res/anim/widget_chooser_slide_up.xml b/res/anim/widget_chooser_slide_up.xml
new file mode 100644
index 000000000..b43ec367e
--- /dev/null
+++ b/res/anim/widget_chooser_slide_up.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fromXDelta="0%p"
+ android:toXDelta="0%p"
+ android:fromYDelta="100%p"
+ android:toYDelta="0%p"
+
+ android:duration="500"
+ android:fillAfter="true" />
diff --git a/res/drawable/add_button.png b/res/drawable/add_button.png
new file mode 100644
index 000000000..0edcfa380
--- /dev/null
+++ b/res/drawable/add_button.png
Binary files differ
diff --git a/res/layout-xlarge/launcher.xml b/res/layout-xlarge/launcher.xml
new file mode 100644
index 000000000..092e018ea
--- /dev/null
+++ b/res/layout-xlarge/launcher.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<com.android.launcher2.DragLayer
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+
+ android:id="@+id/drag_layer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <include layout="@layout/all_apps" />
+
+ <!-- The workspace contains 5 screens of cells -->
+ <com.android.launcher2.Workspace
+ android:id="@+id/workspace"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:defaultScreen="2">
+
+ <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
+
+ </com.android.launcher2.Workspace>
+
+ <com.android.launcher2.DeleteZone
+ android:id="@+id/delete_zone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/delete_zone_padding"
+ android:layout_gravity="top|right"
+
+ android:scaleType="center"
+ android:src="@drawable/delete_zone_selector"
+ android:visibility="gone"
+ launcher:direction="horizontal"
+ />
+ <ImageView
+ android:id="@+id/add_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/delete_zone_padding"
+ android:layout_gravity="top|right"
+
+ android:scaleType="center"
+ android:src="@drawable/add_button"
+
+ android:onClick="onClickAddButton"
+ android:focusable="true"
+ android:clickable="true" />
+
+ <RelativeLayout
+ android:id="@+id/all_apps_button_cluster"
+ android:layout_width="@dimen/button_bar_height"
+ android:layout_height="@dimen/button_bar_height"
+ android:layout_gravity="top|left"
+ android:paddingTop="2dip"
+ >
+ <com.android.launcher2.HandleView
+ style="@style/HotseatButton"
+ android:id="@+id/all_apps_button"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+
+ android:src="@drawable/all_apps_button"
+ launcher:direction="horizontal"
+ />
+ </RelativeLayout>
+ <com.android.launcher2.WidgetChooser
+ android:id="@+id/widget_chooser"
+ android:layout_width="match_parent"
+ android:layout_height="100dip"
+ android:layout_gravity="bottom"
+ android:visibility="gone"
+ />
+</com.android.launcher2.DragLayer>
diff --git a/res/layout/widget_item.xml b/res/layout/widget_item.xml
new file mode 100644
index 000000000..c79bd31a9
--- /dev/null
+++ b/res/layout/widget_item.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="?android:attr/galleryItemBackground"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:focusable="true" />
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<AppWidgetProviderInfo> 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);
+ }
}
/**