summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoe Onorato <joeo@android.com>2010-02-18 15:31:52 -0800
committerJoe Onorato <joeo@android.com>2010-02-18 17:09:55 -0800
commit75fd1ec46da7708bd46183da7999ec891d63140d (patch)
treefb1745879c5acaa3efbf86e28662a3e2ef0a2a8e /src
parentb8fc9e7df69db4b1647ef780f5620836c86f70ea (diff)
downloadandroid_packages_apps_Trebuchet-75fd1ec46da7708bd46183da7999ec891d63140d.tar.gz
android_packages_apps_Trebuchet-75fd1ec46da7708bd46183da7999ec891d63140d.tar.bz2
android_packages_apps_Trebuchet-75fd1ec46da7708bd46183da7999ec891d63140d.zip
DO NOT MERGE - Use the froyo launcher2 in mr3, except for a few unbundling things that can't be merged back.
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/ActivityPicker.java405
-rw-r--r--src/com/android/launcher2/AllAppsList.java50
-rw-r--r--src/com/android/launcher2/AllAppsView.java346
-rw-r--r--src/com/android/launcher2/AppInfoCache.java180
-rw-r--r--src/com/android/launcher2/ApplicationInfo.java96
-rw-r--r--src/com/android/launcher2/CellLayout.java5
-rw-r--r--src/com/android/launcher2/DeleteZone.java4
-rw-r--r--src/com/android/launcher2/DragController.java29
-rw-r--r--src/com/android/launcher2/DragLayer.java7
-rw-r--r--src/com/android/launcher2/DragView.java2
-rw-r--r--src/com/android/launcher2/FastBitmapDrawable.java4
-rw-r--r--src/com/android/launcher2/Folder.java10
-rw-r--r--src/com/android/launcher2/FolderIcon.java10
-rw-r--r--src/com/android/launcher2/IconCache.java140
-rw-r--r--src/com/android/launcher2/InstallShortcutReceiver.java3
-rw-r--r--src/com/android/launcher2/ItemInfo.java31
-rw-r--r--src/com/android/launcher2/Launcher.java299
-rw-r--r--src/com/android/launcher2/LauncherAppWidgetInfo.java3
-rw-r--r--src/com/android/launcher2/LauncherApplication.java19
-rw-r--r--src/com/android/launcher2/LauncherModel.java275
-rw-r--r--src/com/android/launcher2/LauncherProvider.java73
-rw-r--r--src/com/android/launcher2/LauncherSettings.java3
-rw-r--r--src/com/android/launcher2/LiveFolderAdapter.java10
-rw-r--r--src/com/android/launcher2/LiveFolderIcon.java11
-rw-r--r--src/com/android/launcher2/LiveFolderInfo.java8
-rw-r--r--src/com/android/launcher2/ShortcutInfo.java159
-rw-r--r--src/com/android/launcher2/ShortcutsAdapter.java (renamed from src/com/android/launcher2/ApplicationsAdapter.java)19
-rw-r--r--src/com/android/launcher2/UserFolder.java17
-rw-r--r--src/com/android/launcher2/UserFolderInfo.java6
-rw-r--r--src/com/android/launcher2/Utilities.java308
-rw-r--r--src/com/android/launcher2/Workspace.java342
31 files changed, 1232 insertions, 1642 deletions
diff --git a/src/com/android/launcher2/ActivityPicker.java b/src/com/android/launcher2/ActivityPicker.java
deleted file mode 100644
index b6da08e4b..000000000
--- a/src/com/android/launcher2/ActivityPicker.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.launcher2;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.Intent.ShortcutIconResource;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.PaintDrawable;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Displays a list of all activities matching the incoming
- * {@link android.content.Intent#EXTRA_INTENT} query, along with any injected items.
- */
-public class ActivityPicker extends AlertActivity implements
- DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
-
- /**
- * Adapter of items that are displayed in this dialog.
- */
- private PickAdapter mAdapter;
-
- /**
- * Base {@link android.content.Intent} used when building list.
- */
- private Intent mBaseIntent;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final Intent intent = getIntent();
-
- // Read base intent from extras, otherwise assume default
- Parcelable parcel = intent.getParcelableExtra(Intent.EXTRA_INTENT);
- if (parcel instanceof Intent) {
- mBaseIntent = (Intent) parcel;
- } else {
- mBaseIntent = new Intent(Intent.ACTION_MAIN, null);
- mBaseIntent.addCategory(Intent.CATEGORY_DEFAULT);
- }
-
- // Create dialog parameters
- AlertController.AlertParams params = mAlertParams;
- params.mOnClickListener = this;
- params.mOnCancelListener = this;
-
- // Use custom title if provided, otherwise default window title
- if (intent.hasExtra(Intent.EXTRA_TITLE)) {
- params.mTitle = intent.getStringExtra(Intent.EXTRA_TITLE);
- } else {
- params.mTitle = getTitle();
- }
-
- // Build list adapter of pickable items
- List<PickAdapter.Item> items = getItems();
- mAdapter = new PickAdapter(this, items);
- params.mAdapter = mAdapter;
-
- setupAlert();
- }
-
- /**
- * Handle clicking of dialog item by passing back
- * {@link #getIntentForPosition(int)} in {@link #setResult(int, android.content.Intent)}.
- */
- public void onClick(DialogInterface dialog, int which) {
- Intent intent = getIntentForPosition(which);
- setResult(Activity.RESULT_OK, intent);
- finish();
- }
-
- /**
- * Handle canceled dialog by passing back {@link android.app.Activity#RESULT_CANCELED}.
- */
- public void onCancel(DialogInterface dialog) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- }
-
- /**
- * Build the specific {@link android.content.Intent} for a given list position. Convenience
- * method that calls through to {@link PickAdapter.Item#getIntent(android.content.Intent)}.
- */
- protected Intent getIntentForPosition(int position) {
- PickAdapter.Item item = (PickAdapter.Item) mAdapter.getItem(position);
- return item.getIntent(mBaseIntent);
- }
-
- /**
- * Build and return list of items to be shown in dialog. Default
- * implementation mixes activities matching {@link #mBaseIntent} from
- * {@link #putIntentItems(android.content.Intent, java.util.List)} with any injected items from
- * {@link android.content.Intent#EXTRA_SHORTCUT_NAME}. Override this method in subclasses to
- * change the items shown.
- */
- protected List<PickAdapter.Item> getItems() {
- PackageManager packageManager = getPackageManager();
- List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
-
- // Add any injected pick items
- final Intent intent = getIntent();
- ArrayList<String> labels =
- intent.getStringArrayListExtra(Intent.EXTRA_SHORTCUT_NAME);
- ArrayList<ShortcutIconResource> icons =
- intent.getParcelableArrayListExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
-
- if (labels != null && icons != null && labels.size() == icons.size()) {
- for (int i = 0; i < labels.size(); i++) {
- String label = labels.get(i);
- Drawable icon = null;
-
- try {
- // Try loading icon from requested package
- ShortcutIconResource iconResource = icons.get(i);
- Resources res = packageManager.getResourcesForApplication(
- iconResource.packageName);
- icon = res.getDrawable(res.getIdentifier(
- iconResource.resourceName, null, null));
- } catch (NameNotFoundException e) {
- // Ignore
- }
-
- items.add(new PickAdapter.Item(this, label, icon));
- }
- }
-
- // Add any intent items if base was given
- if (mBaseIntent != null) {
- putIntentItems(mBaseIntent, items);
- }
-
- return items;
- }
-
- /**
- * Fill the given list with any activities matching the base {@link android.content.Intent}.
- */
- protected void putIntentItems(Intent baseIntent, List<PickAdapter.Item> items) {
- PackageManager packageManager = getPackageManager();
- List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent,
- 0 /* no flags */);
- Collections.sort(list, new ResolveInfo.DisplayNameComparator(packageManager));
-
- final int listSize = list.size();
- for (int i = 0; i < listSize; i++) {
- ResolveInfo resolveInfo = list.get(i);
- items.add(new PickAdapter.Item(this, packageManager, resolveInfo));
- }
- }
-
- /**
- * Adapter which shows the set of activities that can be performed for a
- * given {@link android.content.Intent}.
- */
- protected static class PickAdapter extends BaseAdapter {
-
- /**
- * Item that appears in a {@link PickAdapter} list.
- */
- public static class Item {
- protected static IconResizer sResizer;
-
- protected IconResizer getResizer(Context context) {
- if (sResizer == null) {
- sResizer = new IconResizer(context);
- }
- return sResizer;
- }
-
- CharSequence label;
- Drawable icon;
- String packageName;
- String className;
- Bundle extras;
-
- /**
- * Create a list item from given label and icon.
- */
- Item(Context context, CharSequence label, Drawable icon) {
- this.label = label;
- this.icon = getResizer(context).createIconThumbnail(icon);
- }
-
- /**
- * Create a list item and fill it with details from the given
- * {@link android.content.pm.ResolveInfo} object.
- */
- Item(Context context, PackageManager pm, ResolveInfo resolveInfo) {
- label = resolveInfo.loadLabel(pm);
- if (label == null && resolveInfo.activityInfo != null) {
- label = resolveInfo.activityInfo.name;
- }
-
- icon = getResizer(context).createIconThumbnail(resolveInfo.loadIcon(pm));
- packageName = resolveInfo.activityInfo.applicationInfo.packageName;
- className = resolveInfo.activityInfo.name;
- }
-
- Intent getIntent(Intent baseIntent) {
- Intent intent = new Intent(baseIntent);
- if (packageName != null && className != null) {
- // Valid package and class, so fill details as normal intent
- intent.setClassName(packageName, className);
- if (extras != null) {
- intent.putExtras(extras);
- }
- } else {
- // No valid package or class, so treat as shortcut with label
- intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
- intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
- }
- return intent;
- }
- }
-
- private final LayoutInflater mInflater;
-
- private List<Item> mItems;
- private int mLayoutRes = R.layout.pick_item;
-
- /**
- * Create an adapter for the given items.
- */
- public PickAdapter(Context context, List<Item> items) {
- mInflater = (LayoutInflater)
- context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mItems = items;
- }
-
- /**
- * {@inheritDoc}
- */
- public int getCount() {
- return mItems.size();
- }
-
- /**
- * {@inheritDoc}
- */
- public Object getItem(int position) {
- return mItems.get(position);
- }
-
- /**
- * {@inheritDoc}
- */
- public long getItemId(int position) {
- return position;
- }
-
- /**
- * {@inheritDoc}
- */
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(mLayoutRes, parent, false);
- }
-
- Item item = (Item) getItem(position);
- TextView textView = (TextView) convertView;
- textView.setText(item.label);
- textView.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null);
-
- return convertView;
- }
- }
-
- /**
- * Utility class to resize icons to match default icon size. Code is mostly
- * borrowed from Launcher.
- */
- private static class IconResizer {
- private int mIconWidth = -1;
- private int mIconHeight = -1;
-
- private final Rect mOldBounds = new Rect();
- private Canvas mCanvas = new Canvas();
- private Resources mResources;
-
- public IconResizer(Context context) {
- mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
- Paint.FILTER_BITMAP_FLAG));
-
- mResources = context.getResources();
- mIconWidth = mIconHeight = (int) mResources.getDimension(
- android.R.dimen.app_icon_size);
- }
-
- /**
- * Returns a Drawable representing the thumbnail of the specified Drawable.
- * The size of the thumbnail is defined by the dimension
- * android.R.dimen.launcher_application_icon_size.
- *
- * This method is not thread-safe and should be invoked on the UI thread only.
- *
- * @param icon The icon to get a thumbnail of.
- *
- * @return A thumbnail for the specified icon or the icon itself if the
- * thumbnail could not be created.
- */
- public Drawable createIconThumbnail(Drawable icon) {
- int width = mIconWidth;
- int height = mIconHeight;
-
- if (icon == null) {
- return null;
- }
-
- final int iconWidth = icon.getIntrinsicWidth();
- final int iconHeight = icon.getIntrinsicHeight();
-
- if (icon instanceof PaintDrawable) {
- PaintDrawable painter = (PaintDrawable) icon;
- painter.setIntrinsicWidth(width);
- painter.setIntrinsicHeight(height);
- }
-
- if (width > 0 && height > 0) {
- if (width < iconWidth || height < iconHeight) {
- final float ratio = (float) iconWidth / iconHeight;
-
- if (iconWidth > iconHeight) {
- height = (int) (width / ratio);
- } else if (iconHeight > iconWidth) {
- width = (int) (height * ratio);
- }
-
- final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
- Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
- final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
- final Canvas canvas = mCanvas;
- canvas.setBitmap(thumb);
- // Copy the old bounds to restore them later
- // If we were to do oldBounds = icon.getBounds(),
- // the call to setBounds() that follows would
- // change the same instance and we would lose the
- // old bounds
- mOldBounds.set(icon.getBounds());
- final int x = (mIconWidth - width) / 2;
- final int y = (mIconHeight - height) / 2;
- icon.setBounds(x, y, x + width, y + height);
- icon.draw(canvas);
- icon.setBounds(mOldBounds);
- icon = new BitmapDrawable(mResources, thumb);
- } else if (iconWidth < width && iconHeight < height) {
- final Bitmap.Config c = Bitmap.Config.ARGB_8888;
- final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
- final Canvas canvas = mCanvas;
- canvas.setBitmap(thumb);
- mOldBounds.set(icon.getBounds());
- final int x = (width - iconWidth) / 2;
- final int y = (height - iconHeight) / 2;
- icon.setBounds(x, y, x + iconWidth, y + iconHeight);
- icon.draw(canvas);
- icon.setBounds(mOldBounds);
- icon = new BitmapDrawable(mResources, thumb);
- }
- }
-
- return icon;
- }
- }
-}
diff --git a/src/com/android/launcher2/AllAppsList.java b/src/com/android/launcher2/AllAppsList.java
index 561b34597..9d4c5b02a 100644
--- a/src/com/android/launcher2/AllAppsList.java
+++ b/src/com/android/launcher2/AllAppsList.java
@@ -17,25 +17,13 @@
package com.android.launcher2;
import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Intent;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.Log;
-import android.os.Process;
-
-import java.lang.ref.WeakReference;
+
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
@@ -46,18 +34,23 @@ class AllAppsList {
public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
/** The list off all apps. */
- public ArrayList<ApplicationInfo> data = new ArrayList(DEFAULT_APPLICATIONS_NUMBER);
+ public ArrayList<ApplicationInfo> data =
+ new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
/** The list of apps that have been added since the last notify() call. */
- public ArrayList<ApplicationInfo> added = new ArrayList(DEFAULT_APPLICATIONS_NUMBER);
+ public ArrayList<ApplicationInfo> added =
+ new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
/** The list of apps that have been removed since the last notify() call. */
- public ArrayList<ApplicationInfo> removed = new ArrayList();
+ public ArrayList<ApplicationInfo> removed = new ArrayList<ApplicationInfo>();
/** The list of apps that have been modified since the last notify() call. */
- public ArrayList<ApplicationInfo> modified = new ArrayList();
+ public ArrayList<ApplicationInfo> modified = new ArrayList<ApplicationInfo>();
+
+ private IconCache mIconCache;
/**
* Boring constructor.
*/
- public AllAppsList() {
+ public AllAppsList(IconCache iconCache) {
+ mIconCache = iconCache;
}
/**
@@ -92,9 +85,8 @@ class AllAppsList {
final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
if (matches.size() > 0) {
- Utilities.BubbleText bubble = new Utilities.BubbleText(context);
for (ResolveInfo info : matches) {
- ApplicationInfo item = AppInfoCache.cache(info, context, bubble);
+ ApplicationInfo item = new ApplicationInfo(info, mIconCache);
data.add(item);
added.add(item);
}
@@ -106,7 +98,7 @@ class AllAppsList {
*/
public void removePackage(String packageName) {
final List<ApplicationInfo> data = this.data;
- for (int i=data.size()-1; i>=0; i--) {
+ for (int i = data.size() - 1; i >= 0; i--) {
ApplicationInfo info = data.get(i);
final ComponentName component = info.intent.getComponent();
if (packageName.equals(component.getPackageName())) {
@@ -115,9 +107,9 @@ class AllAppsList {
}
}
// This is more aggressive than it needs to be.
- AppInfoCache.flush();
+ mIconCache.flush();
}
-
+
/**
* Add and remove icons for this package which has been updated.
*/
@@ -126,13 +118,13 @@ class AllAppsList {
if (matches.size() > 0) {
// Find disabled/removed activities and remove them from data and add them
// to the removed list.
- for (int i=data.size()-1; i>=0; i--) {
+ for (int i = data.size() - 1; i >= 0; i--) {
final ApplicationInfo applicationInfo = data.get(i);
final ComponentName component = applicationInfo.intent.getComponent();
if (packageName.equals(component.getPackageName())) {
if (!findActivity(matches, component)) {
removed.add(applicationInfo);
- AppInfoCache.remove(component);
+ mIconCache.remove(component);
data.remove(i);
}
}
@@ -140,19 +132,19 @@ class AllAppsList {
// Find enabled activities and add them to the adapter
// Also updates existing activities with new labels/icons
- Utilities.BubbleText bubble = new Utilities.BubbleText(context);
int count = matches.size();
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
final ResolveInfo info = matches.get(i);
ApplicationInfo applicationInfo = findApplicationInfoLocked(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
if (applicationInfo == null) {
- applicationInfo = AppInfoCache.cache(info, context, bubble);
+ applicationInfo = new ApplicationInfo(info, mIconCache);
data.add(applicationInfo);
added.add(applicationInfo);
} else {
- AppInfoCache.update(info, applicationInfo, context, bubble);
+ mIconCache.remove(applicationInfo.componentName);
+ mIconCache.getTitleAndIcon(applicationInfo, info);
modified.add(applicationInfo);
}
}
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 13da32915..336f117d1 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -114,8 +114,10 @@ public class AllAppsView extends RSSurfaceView
private boolean mShouldGainFocus;
+ private boolean mHaveSurface = false;
private boolean mZoomDirty = false;
private boolean mAnimateNextZoom;
+ private float mNextZoom;
private float mZoom;
private float mPosX;
private float mVelocity;
@@ -125,20 +127,19 @@ public class AllAppsView extends RSSurfaceView
public static final int ALLOC_PARAMS = 0;
public static final int ALLOC_STATE = 1;
public static final int ALLOC_ICON_IDS = 3;
+ public static final int ALLOC_LABEL_IDS = 4;
+ public static final int ALLOC_VP_CONSTANTS = 5;
public static final int COLUMNS_PER_PAGE = 4;
public static final int ROWS_PER_PAGE = 4;
- public static final int ICON_TEXTURE_WIDTH_PX = 128;
- public static final int ICON_TEXTURE_HEIGHT_PX = 128;
+ public static final int ICON_WIDTH_PX = 64;
+ public static final int ICON_TEXTURE_WIDTH_PX = 74;
+ public static final int SELECTION_TEXTURE_WIDTH_PX = 74 + 20;
- public int SCREEN_WIDTH_PX;
- public int SCREEN_HEIGHT_PX;
-
- public void recompute(int w, int h) {
- SCREEN_WIDTH_PX = 480;
- SCREEN_HEIGHT_PX = 800;
- }
+ public static final int ICON_HEIGHT_PX = 64;
+ public static final int ICON_TEXTURE_HEIGHT_PX = 74;
+ public static final int SELECTION_TEXTURE_HEIGHT_PX = 74 + 20;
}
public AllAppsView(Context context, AttributeSet attrs) {
@@ -158,9 +159,14 @@ public class AllAppsView extends RSSurfaceView
mRS = createRenderScript(true);
}
+ /**
+ * Note that this implementation prohibits this view from ever being reattached.
+ */
@Override
protected void onDetachedFromWindow() {
destroyRenderScript();
+ mRS.mMessageCallback = null;
+ mRS = null;
}
/**
@@ -185,9 +191,12 @@ public class AllAppsView extends RSSurfaceView
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
super.surfaceDestroyed(holder);
- mRollo.mHasSurface = false;
// Without this, we leak mMessageCallback which leaks the context.
mRS.mMessageCallback = null;
+ // We may lose any callbacks that are pending, so make sure that we re-sync that
+ // on the next surfaceChanged.
+ mZoomDirty = true;
+ mHaveSurface = false;
}
@Override
@@ -196,9 +205,10 @@ public class AllAppsView extends RSSurfaceView
super.surfaceChanged(holder, format, w, h);
+ mHaveSurface = true;
+
if (mRollo == null) {
mRollo = new RolloRS();
- mRollo.mHasSurface = true;
mRollo.init(getResources(), w, h);
if (mAllAppsList != null) {
mRollo.setApps(mAllAppsList);
@@ -207,17 +217,34 @@ public class AllAppsView extends RSSurfaceView
gainFocus();
mShouldGainFocus = false;
}
- } else {
- mRollo.mHasSurface = true;
}
mRollo.dirtyCheck();
mRollo.resize(w, h);
- mRS.mMessageCallback = mMessageProc = new AAMessage();
+ if (mRS != null) {
+ mRS.mMessageCallback = mMessageProc = new AAMessage();
+ }
Resources res = getContext().getResources();
int barHeight = (int)res.getDimension(R.dimen.button_bar_height);
+
+ if (mRollo.mUniformAlloc != null) {
+ float tf[] = new float[] {72.f, 72.f,
+ 120.f, 120.f, 0.f, 0.f,
+ 120.f, 680.f,
+ (2.f / 480.f), 0, -((float)w / 2) - 0.25f, -380.25f};
+ if (w > h) {
+ tf[6] = 40.f;
+ tf[7] = h - 40.f;
+ tf[9] = 1.f;
+ tf[10] = -((float)w / 2) - 0.25f;
+ tf[11] = -((float)h / 2) - 0.25f;
+ }
+
+ mRollo.mUniformAlloc.data(tf);
+ }
+
//long endTime = SystemClock.uptimeMillis();
//Log.d(TAG, "surfaceChanged took " + (endTime-startTime) + "ms");
}
@@ -267,7 +294,7 @@ public class AllAppsView extends RSSurfaceView
}
if (gainFocus) {
- if (mRollo != null && mRollo.mHasSurface) {
+ if (mRollo != null) {
gainFocus();
} else {
mShouldGainFocus = true;
@@ -402,15 +429,19 @@ public class AllAppsView extends RSSurfaceView
break;
}
case KeyEvent.KEYCODE_DPAD_LEFT:
- if (currentPageCol > 0) {
- newSelection = currentSelection - 1;
+ if (mLastSelection != SELECTION_HOME) {
+ if (currentPageCol > 0) {
+ newSelection = currentSelection - 1;
+ }
}
handled = true;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
- if ((currentPageCol < Defines.COLUMNS_PER_PAGE - 1) &&
- (currentSelection < iconCount - 1)) {
- newSelection = currentSelection + 1;
+ if (mLastSelection != SELECTION_HOME) {
+ if ((currentPageCol < Defines.COLUMNS_PER_PAGE - 1) &&
+ (currentSelection < iconCount - 1)) {
+ newSelection = currentSelection + 1;
+ }
}
handled = true;
break;
@@ -567,8 +598,7 @@ public class AllAppsView extends RSSurfaceView
&& mCurrentIconIndex >= 0 && mCurrentIconIndex < mAllAppsList.size()) {
ApplicationInfo app = mAllAppsList.get(mCurrentIconIndex);
- Bitmap bmp = Utilities.extractIconFromTexture(app.iconBitmap, getContext());
-
+ Bitmap bmp = app.iconBitmap;
final int w = bmp.getWidth();
final int h = bmp.getHeight();
@@ -576,9 +606,10 @@ public class AllAppsView extends RSSurfaceView
int screenX = mMotionDownRawX - (w / 2);
int screenY = mMotionDownRawY - h;
+ int left = (mDefines.ICON_TEXTURE_WIDTH_PX - mDefines.ICON_WIDTH_PX) / 2;
+ int top = (mDefines.ICON_TEXTURE_HEIGHT_PX - mDefines.ICON_HEIGHT_PX) / 2;
mDragController.startDrag(bmp, screenX, screenY,
0, 0, w, h, this, app, DragController.DRAG_ACTION_COPY);
- bmp.recycle();
mLauncher.closeAllApps(true);
}
@@ -636,10 +667,13 @@ public class AllAppsView extends RSSurfaceView
*/
public void zoom(float zoom, boolean animate) {
cancelLongPress();
- if (mRollo == null || !mRollo.mHasSurface) {
+ mNextZoom = zoom;
+ mAnimateNextZoom = animate;
+ // if we do setZoom while we don't have a surface, we won't
+ // get the callbacks that actually set mZoom.
+ if (mRollo == null || !mHaveSurface) {
mZoomDirty = true;
mZoom = zoom;
- mAnimateNextZoom = animate;
return;
} else {
mRollo.setZoom(zoom, animate);
@@ -655,6 +689,11 @@ public class AllAppsView extends RSSurfaceView
}
public void setApps(ArrayList<ApplicationInfo> list) {
+ if (mRS == null) {
+ // We've been removed from the window. Don't bother with all this.
+ return;
+ }
+
mAllAppsList = list;
if (mRollo != null) {
mRollo.setApps(list);
@@ -667,6 +706,10 @@ public class AllAppsView extends RSSurfaceView
// Not done loading yet. We'll find out about it later.
return;
}
+ if (mRS == null) {
+ // We've been removed from the window. Don't bother with all this.
+ return;
+ }
final int N = list.size();
if (mRollo != null) {
@@ -769,16 +812,16 @@ public class AllAppsView extends RSSurfaceView
private Script.Invokable mInvokeSetZoom;
private ProgramStore mPSIcons;
- private ProgramStore mPSText;
- private ProgramFragment mPFColor;
private ProgramFragment mPFTexMip;
+ private ProgramFragment mPFTexMipAlpha;
private ProgramFragment mPFTexNearest;
private ProgramVertex mPV;
- private ProgramVertex mPVOrtho;
+ private ProgramVertex mPVCurve;
private SimpleMesh mMesh;
- private SimpleMesh mMesh2;
private ProgramVertex.MatrixAllocation mPVA;
+ private Allocation mUniformAlloc;
+
private Allocation mHomeButtonNormal;
private Allocation mHomeButtonFocused;
private Allocation mHomeButtonPressed;
@@ -786,6 +829,10 @@ public class AllAppsView extends RSSurfaceView
private Allocation[] mIcons;
private int[] mIconIds;
private Allocation mAllocIconIds;
+
+ private Allocation[] mLabels;
+ private int[] mLabelIds;
+ private Allocation mAllocLabelIds;
private Allocation mSelectedIcon;
private int[] mTouchYBorders;
@@ -794,9 +841,6 @@ public class AllAppsView extends RSSurfaceView
private Bitmap mSelectionBitmap;
private Canvas mSelectionCanvas;
- boolean mHasSurface = false;
- private boolean mAppsDirty = true;
-
Params mParams;
State mState;
@@ -856,11 +900,9 @@ public class AllAppsView extends RSSurfaceView
mRes = res;
mWidth = width;
mHeight = height;
- mDefines.recompute(width, height);
initProgramVertex();
initProgramFragment();
initProgramStore();
- initMesh();
initGl();
initData();
initTouchState();
@@ -868,41 +910,19 @@ public class AllAppsView extends RSSurfaceView
}
public void initMesh() {
- SimpleMesh.TriangleMeshBuilder tm = new SimpleMesh.TriangleMeshBuilder(mRS, 3,
- SimpleMesh.TriangleMeshBuilder.TEXTURE_0 | SimpleMesh.TriangleMeshBuilder.COLOR);
-
- float y = 0;
- float z = 0;
- for (int ct=0; ct < 200; ct++) {
- float angle = 0;
- float maxAngle = 3.14f * 0.16f;
- float l = 1.f;
-
- l = 1 - ((ct-7) * 0.10f);
- if (ct > 7) {
- angle = maxAngle * (ct - 7) * 0.2f;
- angle = Math.min(angle, maxAngle);
- }
- l = Math.max(0.4f, l);
- l = Math.min(1.0f, l);
-
- y += 0.1f * Math.cos(angle);
- z += 0.1f * Math.sin(angle);
-
- float t = 0.1f * ct;
- float ds = 0.08f;
- tm.setColor(l, l, l, 0.99f);
- tm.setTexture(ds, t);
- tm.addVertex(-0.5f, y, z);
- tm.setTexture(1 - ds, t);
- tm.addVertex(0.5f, y, z);
+ SimpleMesh.TriangleMeshBuilder tm = new SimpleMesh.TriangleMeshBuilder(mRS, 2, 0);
+
+ for (int ct=0; ct < 16; ct++) {
+ float pos = (1.f / (16.f - 1)) * ct;
+ tm.addVertex(0.0f, pos);
+ tm.addVertex(1.0f, pos);
}
- for (int ct=0; ct < (200 * 2 - 2); ct+= 2) {
+ for (int ct=0; ct < (16 * 2 - 2); ct+= 2) {
tm.addTriangle(ct, ct+1, ct+2);
tm.addTriangle(ct+1, ct+3, ct+2);
}
- mMesh2 = tm.create();
- mMesh2.setName("SMMesh");
+ mMesh = tm.create();
+ mMesh.setName("SMCell");
}
void resize(int w, int h) {
@@ -921,12 +941,80 @@ public class AllAppsView extends RSSurfaceView
mPV.setName("PV");
mPV.bindAllocation(mPVA);
- //pva = new ProgramVertex.MatrixAllocation(mRS);
- //pva.setupOrthoWindow(mWidth, mHeight);
- //pvb.setTextureMatrixEnable(true);
- //mPVOrtho = pvb.create();
- //mPVOrtho.setName("PVOrtho");
- //mPVOrtho.bindAllocation(pva);
+ Element.Builder eb = new Element.Builder(mRS);
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "ImgSize");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Position");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "BendPos");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "ScaleOffset");
+ Element e = eb.create();
+
+ mUniformAlloc = Allocation.createSized(mRS, e, 1);
+
+ initMesh();
+ ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
+ String t = new String("void main() {\n" +
+ // Animation
+ " float ani = UNI_Position.z;\n" +
+
+ " float bendY1 = UNI_BendPos.x;\n" +
+ " float bendY2 = UNI_BendPos.y;\n" +
+ " float bendAngle = 47.0 * (3.14 / 180.0);\n" +
+ " float bendDistance = bendY1 * 0.4;\n" +
+ " float distanceDimLevel = 0.6;\n" +
+
+ " float bendStep = (bendAngle / bendDistance) * (bendAngle * 0.5);\n" +
+ " float aDy = cos(bendAngle);\n" +
+ " float aDz = sin(bendAngle);\n" +
+
+ " float scale = (2.0 / 480.0);\n" +
+ " float x = UNI_Position.x + UNI_ImgSize.x * (1.0 - ani) * (ATTRIB_position.x - 0.5);\n" +
+ " float ys= UNI_Position.y + UNI_ImgSize.y * (1.0 - ani) * ATTRIB_position.y;\n" +
+ " float y = 0.0;\n" +
+ " float z = 0.0;\n" +
+ " float lum = 1.0;\n" +
+
+ " float cv = min(ys, bendY1 - bendDistance) - (bendY1 - bendDistance);\n" +
+ " y += cv * aDy;\n" +
+ " z += -cv * aDz;\n" +
+ " cv = clamp(ys, bendY1 - bendDistance, bendY1) - bendY1;\n" + // curve range
+ " lum += cv / bendDistance * distanceDimLevel;\n" +
+ " y += cv * cos(cv * bendStep);\n" +
+ " z += cv * sin(cv * bendStep);\n" +
+
+ " cv = max(ys, bendY2 + bendDistance) - (bendY2 + bendDistance);\n" +
+ " y += cv * aDy;\n" +
+ " z += cv * aDz;\n" +
+ " cv = clamp(ys, bendY2, bendY2 + bendDistance) - bendY2;\n" +
+ " lum -= cv / bendDistance * distanceDimLevel;\n" +
+ " y += cv * cos(cv * bendStep);\n" +
+ " z += cv * sin(cv * bendStep);\n" +
+
+ " y += clamp(ys, bendY1, bendY2);\n" +
+
+ " vec4 pos;\n" +
+ " pos.x = (x + UNI_ScaleOffset.z) * UNI_ScaleOffset.x;\n" +
+ " pos.y = (y + UNI_ScaleOffset.w) * UNI_ScaleOffset.x;\n" +
+ " pos.z = z * UNI_ScaleOffset.x;\n" +
+ " pos.w = 1.0;\n" +
+
+ " pos.x *= 1.0 + ani * 4.0;\n" +
+ " pos.y *= 1.0 + ani * 4.0;\n" +
+ " pos.z -= ani * 1.5;\n" +
+ " lum *= 1.0 - ani;\n" +
+
+ " gl_Position = UNI_MVP * pos;\n" +
+ " varColor.rgba = vec4(lum, lum, lum, 1.0);\n" +
+ " varTex0.xy = ATTRIB_position;\n" +
+ " varTex0.y = 1.0 - varTex0.y;\n" +
+ " varTex0.zw = vec2(0.0, 0.0);\n" +
+ "}\n");
+ sb.setShader(t);
+ sb.addConstant(mUniformAlloc.getType());
+ sb.addInput(mMesh.getVertexType(0).getElement());
+ mPVCurve = sb.create();
+ mPVCurve.setName("PVCurve");
+ mPVCurve.bindAllocation(mPVA);
+ mPVCurve.bindConstants(mUniformAlloc, 1);
mRS.contextBindProgramVertex(mPV);
}
@@ -934,7 +1022,7 @@ public class AllAppsView extends RSSurfaceView
private void initProgramFragment() {
Sampler.Builder sb = new Sampler.Builder(mRS);
sb.setMin(Sampler.Value.LINEAR_MIP_LINEAR);
- sb.setMag(Sampler.Value.LINEAR);
+ sb.setMag(Sampler.Value.NEAREST);
sb.setWrapS(Sampler.Value.CLAMP);
sb.setWrapT(Sampler.Value.CLAMP);
Sampler linear = sb.create();
@@ -944,9 +1032,6 @@ public class AllAppsView extends RSSurfaceView
Sampler nearest = sb.create();
ProgramFragment.Builder bf = new ProgramFragment.Builder(mRS);
- mPFColor = bf.create();
- mPFColor.setName("PFColor");
-
bf.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
ProgramFragment.Builder.Format.RGBA, 0);
mPFTexMip = bf.create();
@@ -956,6 +1041,13 @@ public class AllAppsView extends RSSurfaceView
mPFTexNearest = bf.create();
mPFTexNearest.setName("PFTexNearest");
mPFTexNearest.bindSampler(nearest, 0);
+
+ bf.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
+ ProgramFragment.Builder.Format.ALPHA, 0);
+ mPFTexMipAlpha = bf.create();
+ mPFTexMipAlpha.setName("PFTexMipAlpha");
+ mPFTexMipAlpha.bindSampler(linear, 0);
+
}
private void initProgramStore() {
@@ -967,10 +1059,6 @@ public class AllAppsView extends RSSurfaceView
ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
mPSIcons = bs.create();
mPSIcons.setName("PSIcons");
-
- //bs.setDitherEnable(false);
- //mPSText = bs.create();
- //mPSText.setName("PSText");
}
private void initGl() {
@@ -1008,8 +1096,8 @@ public class AllAppsView extends RSSurfaceView
mParams.save();
mState.save();
- mSelectionBitmap = Bitmap.createBitmap(Defines.ICON_TEXTURE_WIDTH_PX,
- Defines.ICON_TEXTURE_HEIGHT_PX, Bitmap.Config.ARGB_8888);
+ mSelectionBitmap = Bitmap.createBitmap(Defines.SELECTION_TEXTURE_WIDTH_PX,
+ Defines.SELECTION_TEXTURE_HEIGHT_PX, Bitmap.Config.ARGB_8888);
mSelectionCanvas = new Canvas(mSelectionBitmap);
setApps(null);
@@ -1020,11 +1108,12 @@ public class AllAppsView extends RSSurfaceView
private void initRs() {
ScriptC.Builder sb = new ScriptC.Builder(mRS);
- sb.setScript(mRes, R.raw.rollo3);
+ sb.setScript(mRes, R.raw.allapps);
sb.setRoot(true);
sb.addDefines(mDefines);
sb.setType(mParams.mType, "params", Defines.ALLOC_PARAMS);
sb.setType(mState.mType, "state", Defines.ALLOC_STATE);
+ sb.setType(mUniformAlloc.getType(), "vpConstants", Defines.ALLOC_VP_CONSTANTS);
mInvokeMove = sb.addInvokable("move");
mInvokeFling = sb.addInvokable("fling");
mInvokeMoveTo = sb.addInvokable("moveTo");
@@ -1035,22 +1124,15 @@ public class AllAppsView extends RSSurfaceView
mScript.bindAllocation(mParams.mAlloc, Defines.ALLOC_PARAMS);
mScript.bindAllocation(mState.mAlloc, Defines.ALLOC_STATE);
mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
+ mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
+ mScript.bindAllocation(mUniformAlloc, Defines.ALLOC_VP_CONSTANTS);
mRS.contextBindRootScript(mScript);
}
void dirtyCheck() {
- if (mHasSurface) {
- if (mAppsDirty && mAllAppsList != null) {
- for (int i=0; i < mState.iconCount; i++) {
- uploadAppIcon(i, mAllAppsList.get(i));
- }
- saveAppsList();
- mAppsDirty = false;
- }
- if (mZoomDirty) {
- setZoom(mZoom, mAnimateNextZoom);
- }
+ if (mZoomDirty) {
+ setZoom(mNextZoom, mAnimateNextZoom);
}
}
@@ -1065,21 +1147,18 @@ public class AllAppsView extends RSSurfaceView
mIconIds = new int[allocCount];
mAllocIconIds = Allocation.createSized(mRS, Element.USER_I32(mRS), allocCount);
+ mLabels = new Allocation[count];
+ mLabelIds = new int[allocCount];
+ mAllocLabelIds = Allocation.createSized(mRS, Element.USER_I32(mRS), allocCount);
+
Element ie8888 = Element.RGBA_8888(mRS);
mState.iconCount = count;
- long before = SystemClock.uptimeMillis();
for (int i=0; i < mState.iconCount; i++) {
createAppIconAllocations(i, list.get(i));
}
- long after = SystemClock.uptimeMillis();
- //Log.d(TAG, "createAppIconAllocations took " + (after-before) + "ms");
- if (mHasSurface) {
- for (int i=0; i < mState.iconCount; i++) {
- uploadAppIcon(i, list.get(i));
- }
- } else {
- mRollo.mAppsDirty = true;
+ for (int i=0; i < mState.iconCount; i++) {
+ uploadAppIcon(i, list.get(i));
}
saveAppsList();
}
@@ -1098,29 +1177,13 @@ public class AllAppsView extends RSSurfaceView
}
}
- private void frameBitmapAllocMips(Allocation alloc, int w, int h) {
- int black[] = new int[w > h ? w : h];
- Allocation.Adapter2D a = alloc.createAdapter2D();
- int mip = 0;
- while (w > 1 || h > 1) {
- a.subData(0, 0, 1, h, black);
- a.subData(w-1, 0, 1, h, black);
- a.subData(0, 0, w, 1, black);
- a.subData(0, h-1, w, 1, black);
- mip++;
- w = (w + 1) >> 1;
- h = (h + 1) >> 1;
- a.setConstraint(Dimension.LOD, mip);
- }
- a.subData(0, 0, 1, 1, black);
- }
-
private void createAppIconAllocations(int index, ApplicationInfo item) {
- Bitmap bitmap = item.iconBitmap;
- mIcons[index] = Allocation.createFromBitmap(mRS, bitmap, Element.RGBA_8888(mRS), true);
- frameBitmapAllocMips(mIcons[index], bitmap.getWidth(), bitmap.getHeight());
-
+ mIcons[index] = Allocation.createFromBitmap(mRS, item.iconBitmap,
+ Element.RGBA_8888(mRS), true);
+ mLabels[index] = Allocation.createFromBitmap(mRS, item.titleBitmap,
+ Element.A_8(mRS), true);
mIconIds[index] = mIcons[index].getID();
+ mLabelIds[index] = mLabels[index].getID();
}
private void uploadAppIcon(int index, ApplicationInfo item) {
@@ -1131,6 +1194,7 @@ public class AllAppsView extends RSSurfaceView
+ " item=" + item);
}
mIcons[index].uploadToTexture(0);
+ mLabels[index].uploadToTexture(0);
}
/**
@@ -1142,13 +1206,21 @@ public class AllAppsView extends RSSurfaceView
int[] iconIds = new int[count];
mAllocIconIds = Allocation.createSized(mRS, Element.USER_I32(mRS), count);
+ Allocation[] labels = new Allocation[count];
+ int[] labelIds = new int[count];
+ mAllocLabelIds = Allocation.createSized(mRS, Element.USER_I32(mRS), count);
+
final int oldCount = mRollo.mState.iconCount;
System.arraycopy(mIcons, 0, icons, 0, oldCount);
System.arraycopy(mIconIds, 0, iconIds, 0, oldCount);
+ System.arraycopy(mLabels, 0, labels, 0, oldCount);
+ System.arraycopy(mLabelIds, 0, labelIds, 0, oldCount);
mIcons = icons;
mIconIds = iconIds;
+ mLabels = labels;
+ mLabelIds = labelIds;
}
/**
@@ -1160,15 +1232,11 @@ public class AllAppsView extends RSSurfaceView
System.arraycopy(mIcons, index, mIcons, dest, count);
System.arraycopy(mIconIds, index, mIconIds, dest, count);
+ System.arraycopy(mLabels, index, mLabels, dest, count);
+ System.arraycopy(mLabelIds, index, mLabelIds, dest, count);
createAppIconAllocations(index, item);
-
- if (mHasSurface) {
- uploadAppIcon(index, item);
- } else {
- mAppsDirty = true;
- }
-
+ uploadAppIcon(index, item);
mRollo.mState.iconCount++;
}
@@ -1181,12 +1249,16 @@ public class AllAppsView extends RSSurfaceView
System.arraycopy(mIcons, src, mIcons, index, count);
System.arraycopy(mIconIds, src, mIconIds, index, count);
+ System.arraycopy(mLabels, src, mLabels, index, count);
+ System.arraycopy(mLabelIds, src, mLabelIds, index, count);
mRollo.mState.iconCount--;
final int last = mState.iconCount;
mIcons[last] = null;
mIconIds[last] = 0;
+ mLabels[last] = null;
+ mLabelIds[last] = 0;
}
/**
@@ -1196,9 +1268,11 @@ public class AllAppsView extends RSSurfaceView
mRS.contextBindRootScript(null);
mAllocIconIds.data(mIconIds);
+ mAllocLabelIds.data(mLabelIds);
if (mScript != null) { // this happens when we init it
mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
+ mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
}
mState.save();
@@ -1208,7 +1282,9 @@ public class AllAppsView extends RSSurfaceView
if (mInvokeResetWAR != null) {
mInvokeResetWAR.execute();
}
- mRS.contextBindRootScript(mScript);
+ if (mScript != null) {
+ mRS.contextBindRootScript(mScript);
+ }
}
void initTouchState() {
@@ -1313,7 +1389,7 @@ public class AllAppsView extends RSSurfaceView
ApplicationInfo info = mAllAppsList.get(index);
Bitmap selectionBitmap = mSelectionBitmap;
- Utilities.drawSelectedAllAppsBitmap(mSelectionCanvas, selectionBitmap,
+ Utilities.drawSelectedAllAppsBitmap(mSelectionCanvas,
selectionBitmap.getWidth(), selectionBitmap.getHeight(),
pressed == SELECTED_PRESSED, info.iconBitmap);
@@ -1368,10 +1444,12 @@ public class AllAppsView extends RSSurfaceView
Log.d(TAG, "mRollo.mIconIds.length=" + mIconIds.length);
}
Log.d(TAG, "mRollo.mIconIds=" + Arrays.toString(mIconIds));
+ if (mLabelIds != null) {
+ Log.d(TAG, "mRollo.mLabelIds.length=" + mLabelIds.length);
+ }
+ Log.d(TAG, "mRollo.mLabelIds=" + Arrays.toString(mLabelIds));
Log.d(TAG, "mRollo.mTouchXBorders=" + Arrays.toString(mTouchXBorders));
Log.d(TAG, "mRollo.mTouchYBorders=" + Arrays.toString(mTouchYBorders));
- Log.d(TAG, "mRollo.mHasSurface=" + mHasSurface);
- Log.d(TAG, "mRollo.mAppsDirty=" + mAppsDirty);
Log.d(TAG, "mRollo.mState.newPositionX=" + mState.newPositionX);
Log.d(TAG, "mRollo.mState.newTouchDown=" + mState.newTouchDown);
Log.d(TAG, "mRollo.mState.flingVelocity=" + mState.flingVelocity);
diff --git a/src/com/android/launcher2/AppInfoCache.java b/src/com/android/launcher2/AppInfoCache.java
deleted file mode 100644
index e81168ede..000000000
--- a/src/com/android/launcher2/AppInfoCache.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher2;
-
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.net.Uri;
-import android.util.Log;
-import android.os.Process;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Cache of application icons. Icons can be made from any thread.
- */
-public class AppInfoCache {
- private static final String TAG = "Launcher.AppInfoCache";
-
- private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
-
- private static final HashMap<ComponentName, ApplicationInfo> sCache =
- new HashMap<ComponentName, ApplicationInfo>(INITIAL_ICON_CACHE_CAPACITY);
-
- /**
- * no public constructor.
- */
- private AppInfoCache() {
- }
-
- /**
- * For the given ResolveInfo, return an ApplicationInfo and cache the result for later.
- */
- public static ApplicationInfo cache(ResolveInfo info, Context context,
- Utilities.BubbleText bubble) {
- synchronized (sCache) {
- ComponentName componentName = new ComponentName(
- info.activityInfo.applicationInfo.packageName,
- info.activityInfo.name);
- ApplicationInfo application = sCache.get(componentName);
-
- if (application == null) {
- application = new ApplicationInfo();
- application.container = ItemInfo.NO_ID;
-
- updateTitleAndIcon(info, application, context, bubble);
-
- application.setActivity(componentName,
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
- sCache.put(componentName, application);
- }
-
- return application;
- }
- }
-
- /**
- * Update the entry in the in the cache with its new metadata.
- */
- public static void update(ResolveInfo info, ApplicationInfo applicationInfo, Context context,
- Utilities.BubbleText bubble) {
- synchronized (sCache) {
- updateTitleAndIcon(info, applicationInfo, context, bubble);
-
- ComponentName componentName = new ComponentName(
- info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
- sCache.put(componentName, applicationInfo);
- }
- }
-
- /**
- * Remove any records for the supplied ComponentName.
- */
- public static void remove(ComponentName componentName) {
- synchronized (sCache) {
- sCache.remove(componentName);
- }
- }
-
- /**
- * Empty out the cache.
- */
- public static void flush() {
- synchronized (sCache) {
- sCache.clear();
- }
- }
-
- /**
- * Get the icon for the supplied ApplicationInfo. If that activity already
- * exists in the cache, use that.
- */
- public static Drawable getIconDrawable(PackageManager packageManager, ApplicationInfo info) {
- final ResolveInfo resolveInfo = packageManager.resolveActivity(info.intent, 0);
- if (resolveInfo == null) {
- return null;
- }
-
- ComponentName componentName = new ComponentName(
- resolveInfo.activityInfo.applicationInfo.packageName,
- resolveInfo.activityInfo.name);
- ApplicationInfo cached;
- synchronized (sCache) {
- cached = sCache.get(componentName);
- if (cached != null) {
- if (cached.icon == null) {
- cached.icon = resolveInfo.activityInfo.loadIcon(packageManager);
- }
- return cached.icon;
- } else {
- return resolveInfo.activityInfo.loadIcon(packageManager);
- }
- }
- }
-
- /**
- * Go through the cache and disconnect any of the callbacks in the drawables or we
- * leak the previous Home screen on orientation change.
- */
- public static void unbindDrawables() {
- synchronized (sCache) {
- for (ApplicationInfo appInfo: sCache.values()) {
- if (appInfo.icon != null) {
- appInfo.icon.setCallback(null);
- }
- }
- }
- }
-
- /**
- * Update the title and icon. Don't keep a reference to the context!
- */
- private static void updateTitleAndIcon(ResolveInfo info, ApplicationInfo application,
- Context context, Utilities.BubbleText bubble) {
- final PackageManager packageManager = context.getPackageManager();
-
- application.title = info.loadLabel(packageManager);
- if (application.title == null) {
- application.title = info.activityInfo.name;
- }
-
- // TODO: turn this on in froyo, not enough time for testing in mr3
- //if (application.iconBitmap != null) {
- // application.iconBitmap.recycle();
- //}
- application.iconBitmap = Utilities.createAllAppsBitmap(
- info.activityInfo.loadIcon(packageManager),
- application.title.toString(), bubble, context);
- }
-}
-
diff --git a/src/com/android/launcher2/ApplicationInfo.java b/src/com/android/launcher2/ApplicationInfo.java
index ae0e219a0..f50b88930 100644
--- a/src/com/android/launcher2/ApplicationInfo.java
+++ b/src/com/android/launcher2/ApplicationInfo.java
@@ -18,7 +18,9 @@ package com.android.launcher2;
import android.content.ComponentName;
import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
@@ -26,8 +28,7 @@ import android.util.Log;
import java.util.ArrayList;
/**
- * Represents a launchable application. An application is made of a name (or title),
- * an intent and an icon.
+ * Represents an app in AllAppsView.
*/
class ApplicationInfo extends ItemInfo {
@@ -37,53 +38,47 @@ class ApplicationInfo extends ItemInfo {
CharSequence title;
/**
- * The intent used to start the application.
+ * A bitmap of the application's text in the bubble.
*/
- Intent intent;
+ Bitmap titleBitmap;
/**
- * The application icon.
+ * The intent used to start the application.
*/
- Drawable icon;
+ Intent intent;
/**
- * What we show in all apps, including the text.
+ * A bitmap version of the application icon.
*/
Bitmap iconBitmap;
- /**
- * When set to true, indicates that the icon has been resized.
- */
- boolean filtered;
+ ComponentName componentName;
- /**
- * Indicates whether the icon comes from an application's resource (if false)
- * or from a custom Bitmap (if true.)
- */
- boolean customIcon;
+
+ ApplicationInfo() {
+ itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
+ }
/**
- * If isShortcut=true and customIcon=false, this contains a reference to the
- * shortcut icon as an application's resource.
+ * Must not hold the Context.
*/
- Intent.ShortcutIconResource iconResource;
+ public ApplicationInfo(ResolveInfo info, IconCache iconCache) {
+ this.componentName = new ComponentName(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name);
- ApplicationInfo() {
- itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
+ this.container = ItemInfo.NO_ID;
+ this.setActivity(componentName,
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+ iconCache.getTitleAndIcon(this, info);
}
public ApplicationInfo(ApplicationInfo info) {
super(info);
+ componentName = info.componentName;
title = info.title.toString();
intent = new Intent(info.intent);
- if (info.iconResource != null) {
- iconResource = new Intent.ShortcutIconResource();
- iconResource.packageName = info.iconResource.packageName;
- iconResource.resourceName = info.iconResource.resourceName;
- }
- icon = info.icon;
- filtered = info.filtered;
- customIcon = info.customIcon;
}
/**
@@ -102,51 +97,20 @@ class ApplicationInfo extends ItemInfo {
}
@Override
- void onAddToDatabase(ContentValues values) {
- super.onAddToDatabase(values);
-
- String titleStr = title != null ? title.toString() : null;
- values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
-
- String uri = intent != null ? intent.toUri(0) : null;
- values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
-
- if (customIcon) {
- values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
- LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
- Bitmap bitmap = ((FastBitmapDrawable) icon).getBitmap();
- writeBitmap(values, bitmap);
- } else {
- values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
- LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
- if (iconResource != null) {
- values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE,
- iconResource.packageName);
- values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
- iconResource.resourceName);
- }
- }
- }
-
- @Override
public String toString() {
return title.toString();
}
- @Override
- void unbind() {
- super.unbind();
- icon.setCallback(null);
- }
-
-
public static void dumpApplicationInfoList(String tag, String label,
ArrayList<ApplicationInfo> list) {
Log.d(tag, label + " size=" + list.size());
for (ApplicationInfo info: list) {
- Log.d(tag, " title=\"" + info.title + "\" icon=" + info.icon
- + " iconBitmap=" + info.iconBitmap + " filtered=" + info.filtered
- + " customIcon=" + info.customIcon);
+ Log.d(tag, " title=\"" + info.title + "\" titleBitmap=" + info.titleBitmap
+ + " iconBitmap=" + info.iconBitmap);
}
}
+
+ public ShortcutInfo makeShortcut() {
+ return new ShortcutInfo(this);
+ }
}
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 6970875ef..9bf9a465b 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -565,8 +565,11 @@ public class CellLayout extends ViewGroup {
if (lp.dropped) {
lp.dropped = false;
+ final int[] cellXY = mCellXY;
+ getLocationOnScreen(cellXY);
mWallpaperManager.sendWallpaperCommand(getWindowToken(), "android.home.drop",
- childLeft + lp.width / 2, childTop + lp.height / 2, 0, null);
+ cellXY[0] + childLeft + lp.width / 2,
+ cellXY[1] + childTop + lp.height / 2, 0, null);
}
}
}
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index ec4bc534c..fabeb4a3b 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -101,9 +101,9 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
if (source instanceof UserFolder) {
final UserFolder userFolder = (UserFolder) source;
final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();
- // item must be an ApplicationInfo otherwise it couldn't have been in the folder
+ // Item must be a ShortcutInfo otherwise it couldn't have been in the folder
// in the first place.
- userFolderInfo.remove((ApplicationInfo)item);
+ userFolderInfo.remove((ShortcutInfo)item);
}
}
if (item instanceof UserFolderInfo) {
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 590ca6927..daabbcc4c 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -18,25 +18,18 @@ package com.android.launcher2;
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.IBinder;
import android.os.Handler;
import android.os.Vibrator;
-import android.os.SystemClock;
-import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
-import android.view.ViewGroup;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
import java.util.ArrayList;
@@ -44,6 +37,7 @@ import java.util.ArrayList;
* Class for initiating a drag within a view or across multiple views.
*/
public class DragController {
+ @SuppressWarnings({"UnusedDeclaration"})
private static final String TAG = "Launcher.DragController";
/** Indicates the drag is a move. */
@@ -113,6 +107,8 @@ public class DragController {
/** The view that will be scrolled when dragging to the left and right edges of the screen. */
private View mScrollView;
+ private View mMoveTarget;
+
private DragScroller mDragScroller;
private int mScrollState = SCROLL_OUTSIDE_ZONE;
private ScrollRunnable mScrollRunnable = new ScrollRunnable();
@@ -147,7 +143,6 @@ public class DragController {
* Used to create a new DragLayer from XML.
*
* @param context The application's context.
- * @param attrs The attribtues set containing the Workspace's customization values.
*/
public DragController(Context context) {
mContext = context;
@@ -159,7 +154,7 @@ public class DragController {
*
* @param v The view that is being dragged
* @param source An object representing where the drag originated
- * @param info The data associated with the object that is being dragged
+ * @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}
*/
@@ -195,7 +190,7 @@ public class DragController {
* @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 info The data associated with the object that is being dragged
+ * @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}
*/
@@ -275,6 +270,7 @@ public class DragController {
* || super.dispatchKeyEvent(event);
* </pre>
*/
+ @SuppressWarnings({"UnusedDeclaration"})
public boolean dispatchKeyEvent(KeyEvent event) {
return mDragging;
}
@@ -343,6 +339,17 @@ public class DragController {
}
/**
+ * Sets the view that should handle move events.
+ */
+ void setMoveTarget(View view) {
+ mMoveTarget = view;
+ }
+
+ public boolean dispatchUnhandledMove(View focused, int direction) {
+ return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
+ }
+
+ /**
* Call this from a drag source view.
*/
public boolean onTouchEvent(MotionEvent ev) {
@@ -377,7 +384,7 @@ public class DragController {
// Drop on someone?
final int[] coordinates = mCoordinatesTemp;
- DropTarget dropTarget = findDropTarget((int) screenX, (int) screenY, coordinates);
+ DropTarget dropTarget = findDropTarget(screenX, screenY, coordinates);
if (dropTarget != null) {
if (mLastDropTarget == dropTarget) {
dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 7ae98917d..c68320764 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -18,9 +18,9 @@ package com.android.launcher2;
import android.content.Context;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.KeyEvent;
+import android.view.View;
import android.widget.FrameLayout;
/**
@@ -57,4 +57,9 @@ public class DragLayer extends FrameLayout {
public boolean onTouchEvent(MotionEvent ev) {
return mDragController.onTouchEvent(ev);
}
+
+ @Override
+ public boolean dispatchUnhandledMove(View focused, int direction) {
+ return mDragController.dispatchUnhandledMove(focused, direction);
+ }
}
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 7a86273e6..248712ed3 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -37,7 +37,7 @@ import android.view.WindowManagerImpl;
public class DragView extends View implements TweenCallback {
// Number of pixels to add to the dragged item for scaling. Should be even for pixel alignment.
- private static final int DRAG_SCALE = 24;
+ private static final int DRAG_SCALE = 40;
private Bitmap mBitmap;
private Paint mPaint;
diff --git a/src/com/android/launcher2/FastBitmapDrawable.java b/src/com/android/launcher2/FastBitmapDrawable.java
index db2c01c4f..850535e67 100644
--- a/src/com/android/launcher2/FastBitmapDrawable.java
+++ b/src/com/android/launcher2/FastBitmapDrawable.java
@@ -67,6 +67,10 @@ class FastBitmapDrawable extends Drawable {
return mBitmap.getHeight();
}
+ public void setBitmap(Bitmap b) {
+ mBitmap = b;
+ }
+
public Bitmap getBitmap() {
return mBitmap;
}
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 4f66ad052..7c35f7997 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -46,7 +46,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
/**
* Which item is being dragged
*/
- protected ApplicationInfo mDragItem;
+ protected ShortcutInfo mDragItem;
private boolean mCloneInfo;
/**
@@ -74,7 +74,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
public void onItemClick(AdapterView parent, View v, int position, long id) {
- ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
+ ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
mLauncher.startActivitySafely(app.intent);
}
@@ -93,9 +93,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
return false;
}
- ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
+ ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
if (mCloneInfo) {
- app = new ApplicationInfo(app);
+ app = new ShortcutInfo(app);
}
mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
@@ -118,7 +118,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
/**
* Sets the adapter used to populate the content area. The adapter must only
- * contains ApplicationInfo items.
+ * contains ShortcutInfo items.
*
* @param adapter The list of applications to display in the folder.
*/
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 85fc3a754..826336c9f 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -48,7 +48,6 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
final Resources resources = launcher.getResources();
Drawable d = resources.getDrawable(R.drawable.ic_launcher_folder);
- d = Utilities.createIconThumbnail(d, launcher);
icon.mCloseIcon = d;
icon.mOpenIcon = resources.getDrawable(R.drawable.ic_launcher_folder_open);
icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
@@ -77,8 +76,13 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
- final ApplicationInfo item = (ApplicationInfo) dragInfo;
- // TODO: update open folder that is looking at this data
+ ShortcutInfo item;
+ if (dragInfo instanceof ApplicationInfo) {
+ // Came from all apps -- make a copy
+ item = ((ApplicationInfo)dragInfo).makeShortcut();
+ } else {
+ item = (ShortcutInfo)dragInfo;
+ }
mInfo.add(item);
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
}
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
new file mode 100644
index 000000000..855d91431
--- /dev/null
+++ b/src/com/android/launcher2/IconCache.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.util.Log;
+import android.os.Process;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Cache of application icons. Icons can be made from any thread.
+ */
+public class IconCache {
+ private static final String TAG = "Launcher.IconCache";
+
+ private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
+
+ private static class CacheEntry {
+ public Bitmap icon;
+ public String title;
+ public Bitmap titleBitmap;
+ }
+
+ private LauncherApplication mContext;
+ private PackageManager mPackageManager;
+ private Utilities.BubbleText mBubble;
+ private final HashMap<ComponentName, CacheEntry> mCache =
+ new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
+
+ public IconCache(LauncherApplication context) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mBubble = new Utilities.BubbleText(context);
+ }
+
+ /**
+ * Remove any records for the supplied ComponentName.
+ */
+ public void remove(ComponentName componentName) {
+ synchronized (mCache) {
+ mCache.remove(componentName);
+ }
+ }
+
+ /**
+ * Empty out the cache.
+ */
+ public void flush() {
+ synchronized (mCache) {
+ mCache.clear();
+ }
+ }
+
+ /**
+ * Fill in "application" with the icon and label for "info."
+ */
+ public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info) {
+ synchronized (mCache) {
+ CacheEntry entry = cacheLocked(application.componentName, info);
+ if (entry.titleBitmap == null) {
+ entry.titleBitmap = mBubble.createTextBitmap(entry.title.toString());
+ }
+
+ application.title = entry.title;
+ application.titleBitmap = entry.titleBitmap;
+ application.iconBitmap = entry.icon;
+ }
+ }
+
+ public Bitmap getIcon(Intent intent) {
+ final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
+ ComponentName component = intent.getComponent();
+
+ if (resolveInfo == null || component == null) {
+ return null;
+ }
+
+ CacheEntry entry = cacheLocked(component, resolveInfo);
+ return entry.icon;
+ }
+
+ public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo) {
+ if (resolveInfo == null || component == null) {
+ return null;
+ }
+
+ CacheEntry entry = cacheLocked(component, resolveInfo);
+ return entry.icon;
+ }
+
+ private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
+ CacheEntry entry = mCache.get(componentName);
+ if (entry == null) {
+ entry = new CacheEntry();
+
+ mCache.put(componentName, entry);
+
+ entry.title = info.loadLabel(mPackageManager).toString();
+ if (entry.title == null) {
+ entry.title = info.activityInfo.name;
+ }
+ entry.icon = Utilities.createIconBitmap(
+ info.activityInfo.loadIcon(mPackageManager), mContext);
+ }
+ return entry;
+ }
+}
+
diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java
index 45ff24e17..9a2f73fcd 100644
--- a/src/com/android/launcher2/InstallShortcutReceiver.java
+++ b/src/com/android/launcher2/InstallShortcutReceiver.java
@@ -63,7 +63,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
// different places)
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
- Launcher.addShortcut(context, data, cell, true);
+ ((LauncherApplication)context.getApplicationContext()).getModel()
+ .addShortcut(context, data, cell, true);
Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
Toast.LENGTH_SHORT).show();
} else {
diff --git a/src/com/android/launcher2/ItemInfo.java b/src/com/android/launcher2/ItemInfo.java
index f04880ddd..ca2ea86c8 100644
--- a/src/com/android/launcher2/ItemInfo.java
+++ b/src/com/android/launcher2/ItemInfo.java
@@ -112,21 +112,26 @@ class ItemInfo {
}
}
+ static byte[] flattenBitmap(Bitmap bitmap) {
+ // Try go guesstimate how much space the icon will take when serialized
+ // to avoid unnecessary allocations/copies during the write.
+ int size = bitmap.getWidth() * bitmap.getHeight() * 4;
+ ByteArrayOutputStream out = new ByteArrayOutputStream(size);
+ try {
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+ out.flush();
+ out.close();
+ return out.toByteArray();
+ } catch (IOException e) {
+ Log.w("Favorite", "Could not write icon");
+ return null;
+ }
+ }
+
static void writeBitmap(ContentValues values, Bitmap bitmap) {
if (bitmap != null) {
- // Try go guesstimate how much space the icon will take when serialized
- // to avoid unnecessary allocations/copies during the write.
- int size = bitmap.getWidth() * bitmap.getHeight() * 4;
- ByteArrayOutputStream out = new ByteArrayOutputStream(size);
- try {
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
- out.flush();
- out.close();
-
- values.put(LauncherSettings.Favorites.ICON, out.toByteArray());
- } catch (IOException e) {
- Log.w("Favorite", "Could not write icon");
- }
+ byte[] data = flattenBitmap(bitmap);
+ values.put(LauncherSettings.Favorites.ICON, data);
}
}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 7a4e2bc2c..2a6fd56f5 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -19,7 +19,6 @@ package com.android.launcher2;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.ISearchManager;
import android.app.SearchManager;
import android.app.StatusBarManager;
import android.app.WallpaperManager;
@@ -43,16 +42,11 @@ import android.graphics.Rect;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.provider.ContactsContract;
import android.provider.LiveFolders;
-import android.telephony.PhoneNumberUtils;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -67,6 +61,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnLongClickListener;
+import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
@@ -99,6 +94,8 @@ public final class Launcher extends Activity
private static final int WALLPAPER_SCREENS_SPAN = 2;
private static final int MENU_GROUP_ADD = 1;
+ private static final int MENU_GROUP_WALLPAPER = MENU_GROUP_ADD + 1;
+
private static final int MENU_ADD = Menu.FIRST + 1;
private static final int MENU_WALLPAPER_SETTINGS = MENU_ADD + 1;
private static final int MENU_SEARCH = MENU_WALLPAPER_SETTINGS + 1;
@@ -197,6 +194,7 @@ public final class Launcher extends Activity
private Bundle mSavedInstanceState;
private LauncherModel mModel;
+ private IconCache mIconCache;
private ArrayList<ItemInfo> mDesktopItems = new ArrayList<ItemInfo>();
private static HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
@@ -204,13 +202,13 @@ public final class Launcher extends Activity
private ImageView mPreviousView;
private ImageView mNextView;
- private boolean mUtsTestMode;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mModel = ((LauncherApplication)getApplication()).setLauncher(this);
+ LauncherApplication app = ((LauncherApplication)getApplication());
+ mModel = app.setLauncher(this);
+ mIconCache = app.getIconCache();
mDragController = new DragController(this);
mInflater = getLayoutInflater();
@@ -279,7 +277,7 @@ public final class Launcher extends Activity
localeConfiguration.mnc = mnc;
writeConfiguration(this, localeConfiguration);
- AppInfoCache.flush();
+ mIconCache.flush();
}
}
@@ -411,7 +409,6 @@ public final class Launcher extends Activity
super.onResume();
mPaused = false;
- mUtsTestMode = SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1;
if (mRestoring) {
mWorkspaceLoading = true;
@@ -454,6 +451,27 @@ public final class Launcher extends Activity
return null;
}
+ // We can't hide the IME if it was forced open. So don't bother
+ /*
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+
+ if (hasFocus) {
+ final InputMethodManager inputManager = (InputMethodManager)
+ getSystemService(Context.INPUT_METHOD_SERVICE);
+ WindowManager.LayoutParams lp = getWindow().getAttributes();
+ inputManager.hideSoftInputFromWindow(lp.token, 0, new android.os.ResultReceiver(new
+ android.os.Handler()) {
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ Log.d(TAG, "ResultReceiver got resultCode=" + resultCode);
+ }
+ });
+ Log.d(TAG, "called hideSoftInputFromWindow from onWindowFocusChanged");
+ }
+ }
+ */
+
private boolean acceptFilter() {
final InputMethodManager inputManager = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -462,10 +480,6 @@ public final class Launcher extends Activity
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (mUtsTestMode) {
- return handleUtsTestModeKeyDown(keyCode, event);
- }
-
boolean handled = super.onKeyDown(keyCode, event);
if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
@@ -481,50 +495,9 @@ public final class Launcher extends Activity
}
}
- return handled;
- }
-
- public boolean handleUtsTestModeKeyDown(int keyCode, KeyEvent event) {
- Log.d(TAG, "UTS-TEST-MODE");
- boolean handled = super.onKeyDown(keyCode, event);
- if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
- boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
- keyCode, event);
- if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
- // something usable has been typed - dispatch it now.
- final String str = mDefaultKeySsb.toString();
-
- boolean isDialable = true;
- final int count = str.length();
- for (int i = 0; i < count; i++) {
- if (!PhoneNumberUtils.isReallyDialable(str.charAt(i))) {
- isDialable = false;
- break;
- }
- }
- Intent intent;
- if (isDialable) {
- intent = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", str, null));
- } else {
- intent = new Intent(ContactsContract.Intents.UI.FILTER_CONTACTS_ACTION);
- intent.putExtra(ContactsContract.Intents.UI.FILTER_TEXT_EXTRA_KEY, str);
- }
-
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
- try {
- startActivity(intent);
- } catch (android.content.ActivityNotFoundException ex) {
- // Oh well... no one knows how to filter/dial. Life goes on.
- }
-
- mDefaultKeySsb.clear();
- mDefaultKeySsb.clearSpans();
- Selection.setSelection(mDefaultKeySsb, 0);
-
- return true;
- }
+ // Eat the long press event so the keyboard doesn't come up.
+ if (keyCode == KeyEvent.KEYCODE_MENU && event.isLongPress()) {
+ return true;
}
return handled;
@@ -603,6 +576,7 @@ public final class Launcher extends Activity
mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
final Workspace workspace = mWorkspace;
+ workspace.setHapticFeedbackEnabled(false);
DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
mDeleteZone = deleteZone;
@@ -610,6 +584,7 @@ public final class Launcher extends Activity
mHandleView = (HandleView) findViewById(R.id.all_apps_button);
mHandleView.setLauncher(this);
mHandleView.setOnClickListener(this);
+ mHandleView.setOnLongClickListener(this);
mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
@@ -634,6 +609,7 @@ public final class Launcher extends Activity
dragController.setDragScoller(workspace);
dragController.setDragListener(deleteZone);
dragController.setScrollView(dragLayer);
+ dragController.setMoveTarget(workspace);
// The order here is bottom to top.
dragController.addDropTarget(workspace);
@@ -661,7 +637,7 @@ public final class Launcher extends Activity
*
* @return A View inflated from R.layout.application.
*/
- View createShortcut(ApplicationInfo info) {
+ View createShortcut(ShortcutInfo info) {
return createShortcut(R.layout.application,
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info);
}
@@ -675,18 +651,12 @@ public final class Launcher extends Activity
*
* @return A View inflated from layoutResId.
*/
- View createShortcut(int layoutResId, ViewGroup parent, ApplicationInfo info) {
+ View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
- if (info.icon == null) {
- info.icon = AppInfoCache.getIconDrawable(getPackageManager(), info);
- }
- if (!info.filtered) {
- info.icon = Utilities.createIconThumbnail(info.icon, this);
- info.filtered = true;
- }
-
- favorite.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
+ favorite.setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(info.getIcon(mIconCache)),
+ null, null);
favorite.setText(info.title);
favorite.setTag(info);
favorite.setOnClickListener(this);
@@ -704,39 +674,17 @@ public final class Launcher extends Activity
cellInfo.screen = mWorkspace.getCurrentScreen();
if (!findSingleSlot(cellInfo)) return;
- final ApplicationInfo info = infoFromApplicationIntent(context, data);
- if (info != null) {
- mWorkspace.addApplicationShortcut(info, cellInfo, isWorkspaceLocked());
- }
- }
+ final ShortcutInfo info = mModel.getShortcutInfo(context.getPackageManager(),
+ data, context);
- private static ApplicationInfo infoFromApplicationIntent(Context context, Intent data) {
- ComponentName component = data.getComponent();
- PackageManager packageManager = context.getPackageManager();
- ActivityInfo activityInfo = null;
- try {
- activityInfo = packageManager.getActivityInfo(component, 0 /* no flags */);
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Couldn't find ActivityInfo for selected application", e);
- }
-
- if (activityInfo != null) {
- ApplicationInfo itemInfo = new ApplicationInfo();
-
- itemInfo.title = activityInfo.loadLabel(packageManager);
- if (itemInfo.title == null) {
- itemInfo.title = activityInfo.name;
- }
-
- itemInfo.setActivity(component, Intent.FLAG_ACTIVITY_NEW_TASK |
+ if (info != null) {
+ info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- itemInfo.icon = activityInfo.loadIcon(packageManager);
- itemInfo.container = ItemInfo.NO_ID;
-
- return itemInfo;
+ info.container = ItemInfo.NO_ID;
+ mWorkspace.addApplicationShortcut(info, cellInfo, isWorkspaceLocked());
+ } else {
+ Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
}
-
- return null;
}
/**
@@ -749,7 +697,7 @@ public final class Launcher extends Activity
cellInfo.screen = mWorkspace.getCurrentScreen();
if (!findSingleSlot(cellInfo)) return;
- final ApplicationInfo info = addShortcut(this, data, cellInfo, false);
+ final ShortcutInfo info = mModel.addShortcut(this, data, cellInfo, false);
if (!mRestoring) {
final View view = createShortcut(info);
@@ -816,61 +764,6 @@ public final class Launcher extends Activity
return mAppWidgetHost;
}
- static ApplicationInfo addShortcut(Context context, Intent data,
- CellLayout.CellInfo cellInfo, boolean notify) {
-
- final ApplicationInfo info = infoFromShortcutIntent(context, data);
- LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
- cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
-
- return info;
- }
-
- private static ApplicationInfo infoFromShortcutIntent(Context context, Intent data) {
- Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
- String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
- Bitmap bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
-
- Drawable icon = null;
- boolean filtered = false;
- boolean customIcon = false;
- ShortcutIconResource iconResource = null;
-
- if (bitmap != null) {
- icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, context));
- filtered = true;
- customIcon = true;
- } else {
- Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
- if (extra != null && extra instanceof ShortcutIconResource) {
- try {
- iconResource = (ShortcutIconResource) extra;
- final PackageManager packageManager = context.getPackageManager();
- Resources resources = packageManager.getResourcesForApplication(
- iconResource.packageName);
- final int id = resources.getIdentifier(iconResource.resourceName, null, null);
- icon = resources.getDrawable(id);
- } catch (Exception e) {
- Log.w(TAG, "Could not load shortcut icon: " + extra);
- }
- }
- }
-
- if (icon == null) {
- icon = context.getPackageManager().getDefaultActivityIcon();
- }
-
- final ApplicationInfo info = new ApplicationInfo();
- info.icon = icon;
- info.filtered = filtered;
- info.title = name;
- info.intent = intent;
- info.customIcon = customIcon;
- info.iconResource = iconResource;
-
- return info;
- }
-
void closeSystemDialogs() {
getWindow().closeAllPanels();
@@ -987,7 +880,6 @@ public final class Launcher extends Activity
mModel.stopLoader();
unbindDesktopItems();
- AppInfoCache.unbindDrawables();
getContentResolver().unregisterContentObserver(mWidgetObserver);
@@ -1079,10 +971,11 @@ public final class Launcher extends Activity
}
super.onCreateOptionsMenu(menu);
+
menu.add(MENU_GROUP_ADD, MENU_ADD, 0, R.string.menu_add)
.setIcon(android.R.drawable.ic_menu_add)
.setAlphabeticShortcut('A');
- menu.add(0, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)
+ menu.add(MENU_GROUP_WALLPAPER, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)
.setIcon(android.R.drawable.ic_menu_gallery)
.setAlphabeticShortcut('W');
menu.add(0, MENU_SEARCH, 0, R.string.menu_search)
@@ -1107,8 +1000,22 @@ public final class Launcher extends Activity
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- mMenuAddInfo = mWorkspace.findAllVacantCells(null);
- menu.setGroupEnabled(MENU_GROUP_ADD, mMenuAddInfo != null && mMenuAddInfo.valid);
+ // If all apps is animating, don't show the menu, because we don't know
+ // which one to show.
+ if (mAllAppsGrid.isVisible() && !mAllAppsGrid.isOpaque()) {
+ return false;
+ }
+
+ // Only show the add and wallpaper options when we're not in all apps.
+ boolean visible = !mAllAppsGrid.isOpaque();
+ menu.setGroupVisible(MENU_GROUP_ADD, visible);
+ menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
+
+ // Disable add if the workspace is full.
+ if (visible) {
+ mMenuAddInfo = mWorkspace.findAllVacantCells(null);
+ menu.setGroupEnabled(MENU_GROUP_ADD, mMenuAddInfo != null && mMenuAddInfo.valid);
+ }
return true;
}
@@ -1276,7 +1183,6 @@ public final class Launcher extends Activity
String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
Drawable icon = null;
- boolean filtered = false;
Intent.ShortcutIconResource iconResource = null;
Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
@@ -1298,8 +1204,7 @@ public final class Launcher extends Activity
}
final LiveFolderInfo info = new LiveFolderInfo();
- info.icon = icon;
- info.filtered = filtered;
+ info.icon = Utilities.createIconBitmap(icon, context);
info.title = name;
info.iconResource = iconResource;
info.uri = data.getData();
@@ -1451,9 +1356,9 @@ public final class Launcher extends Activity
*/
public void onClick(View v) {
Object tag = v.getTag();
- if (tag instanceof ApplicationInfo) {
+ if (tag instanceof ShortcutInfo) {
// Open shortcut
- final Intent intent = ((ApplicationInfo) tag).intent;
+ final Intent intent = ((ShortcutInfo)tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(
@@ -1542,14 +1447,21 @@ public final class Launcher extends Activity
if (!isAllAppsVisible()) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- showPreviousPreview(v);
+ showPreviews(v);
}
return true;
case R.id.next_screen:
if (!isAllAppsVisible()) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- showNextPreview(v);
+ showPreviews(v);
+ }
+ return true;
+ case R.id.all_apps_button:
+ if (!isAllAppsVisible()) {
+ mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+ showPreviews(v);
}
return true;
}
@@ -1574,6 +1486,8 @@ public final class Launcher extends Activity
if (cellInfo.valid) {
// User long pressed on empty space
mWorkspace.setAllowLongPress(false);
+ mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showAddDialog(cellInfo);
}
} else {
@@ -1612,29 +1526,19 @@ public final class Launcher extends Activity
v.setTag(null);
}
- private void showPreviousPreview(View anchor) {
- int current = mWorkspace.getCurrentScreen();
- if (current <= 0) return;
-
+ private void showPreviews(View anchor) {
showPreviews(anchor, 0, mWorkspace.getChildCount());
}
- private void showNextPreview(View anchor) {
- int current = mWorkspace.getCurrentScreen();
- if (current >= mWorkspace.getChildCount() - 1) return;
-
- showPreviews(anchor, 0, mWorkspace.getChildCount());
- }
-
private void showPreviews(final View anchor, int start, int end) {
- Resources resources = getResources();
+ final Resources resources = getResources();
+ final Workspace workspace = mWorkspace;
- Workspace workspace = mWorkspace;
CellLayout cell = ((CellLayout) workspace.getChildAt(start));
float max = workspace.getChildCount();
- Rect r = new Rect();
+ final Rect r = new Rect();
resources.getDrawable(R.drawable.preview_background).getPadding(r);
int extraW = (int) ((r.left + r.right) * max);
int extraH = r.top + r.bottom;
@@ -1665,10 +1569,10 @@ public final class Launcher extends Activity
ImageView image = new ImageView(this);
cell = (CellLayout) workspace.getChildAt(i);
- Bitmap bitmap = Bitmap.createBitmap((int) sWidth, (int) sHeight,
+ final Bitmap bitmap = Bitmap.createBitmap((int) sWidth, (int) sHeight,
Bitmap.Config.ARGB_8888);
-
- Canvas c = new Canvas(bitmap);
+
+ final Canvas c = new Canvas(bitmap);
c.scale(scale, scale);
c.translate(-cell.getLeftPadding(), -cell.getTopPadding());
cell.dispatchDraw(c);
@@ -1686,8 +1590,8 @@ public final class Launcher extends Activity
bitmaps.add(bitmap);
}
-
- PopupWindow p = new PopupWindow(this);
+
+ final PopupWindow p = new PopupWindow(this);
p.setContentView(preview);
p.setWidth((int) (sWidth * count + extraW));
p.setHeight((int) (sHeight + extraH));
@@ -1731,10 +1635,6 @@ public final class Launcher extends Activity
}
}
- View getDrawerHandle() {
- return mHandleView;
- }
-
Workspace getWorkspace() {
return mWorkspace;
}
@@ -1885,22 +1785,14 @@ public final class Launcher extends Activity
return mAllAppsGrid.isVisible();
}
- boolean isAllAppsOpaque() {
- return mAllAppsGrid.isOpaque();
- }
-
void showAllApps(boolean animated) {
mAllAppsGrid.zoom(1.0f, animated);
- //mWorkspace.hide();
-
- mWorkspace.startFading(false);
mAllAppsGrid.setFocusable(true);
mAllAppsGrid.requestFocus();
// TODO: fade these two too
mDeleteZone.setVisibility(View.GONE);
- //mHandleView.setVisibility(View.GONE);
}
/**
@@ -1943,13 +1835,6 @@ public final class Launcher extends Activity
mAllAppsGrid.zoom(0.0f, animated);
mAllAppsGrid.setFocusable(false);
mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
- mWorkspace.startFading(true);
-
- // TODO: fade these two too
- /*
- mDeleteZone.setVisibility(View.VISIBLE);
- mHandleView.setVisibility(View.VISIBLE);
- */
}
}
@@ -2162,7 +2047,7 @@ public final class Launcher extends Activity
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- final View shortcut = createShortcut((ApplicationInfo) item);
+ final View shortcut = createShortcut((ShortcutInfo)item);
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
@@ -2304,7 +2189,7 @@ public final class Launcher extends Activity
*/
public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps) {
removeDialog(DIALOG_CREATE_SHORTCUT);
- mWorkspace.removeShortcutsForPackage(packageName);
+ mWorkspace.removeItemsForPackage(packageName);
mAllAppsGrid.removeApps(apps);
}
diff --git a/src/com/android/launcher2/LauncherAppWidgetInfo.java b/src/com/android/launcher2/LauncherAppWidgetInfo.java
index 25db72bed..a28973bc4 100644
--- a/src/com/android/launcher2/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher2/LauncherAppWidgetInfo.java
@@ -25,7 +25,8 @@ import android.content.ContentValues;
class LauncherAppWidgetInfo extends ItemInfo {
/**
- * Identifier for this widget when talking with {@link AppWidgetManager} for updates.
+ * Identifier for this widget when talking with
+ * {@link android.appwidget.AppWidgetManager} for updates.
*/
int appWidgetId;
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index 9b6352433..183dbf571 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -18,7 +18,6 @@ package com.android.launcher2;
import android.app.Application;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
@@ -26,11 +25,8 @@ import android.os.Handler;
import dalvik.system.VMRuntime;
public class LauncherApplication extends Application {
- public final LauncherModel mModel;
-
- public LauncherApplication() {
- mModel = new LauncherModel(this);
- }
+ public LauncherModel mModel;
+ public IconCache mIconCache;
@Override
public void onCreate() {
@@ -38,6 +34,9 @@ public class LauncherApplication extends Application {
super.onCreate();
+ mIconCache = new IconCache(this);
+ mModel = new LauncherModel(this, mIconCache);
+
// Register intent receivers
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -80,4 +79,12 @@ public class LauncherApplication extends Application {
mModel.initialize(launcher);
return mModel;
}
+
+ IconCache getIconCache() {
+ return mIconCache;
+ }
+
+ LauncherModel getModel() {
+ return mModel;
+ }
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 97fa554c2..43daa9c0e 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -16,20 +16,27 @@
package com.android.launcher2;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
+import android.content.Intent.ShortcutIconResource;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
+import android.os.Parcelable;
+import android.os.RemoteException;
import android.util.Log;
import android.os.Process;
import android.os.SystemClock;
@@ -60,7 +67,10 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mBeforeFirstLoad = true;
private WeakReference<Callbacks> mCallbacks;
- private AllAppsList mAllAppsList = new AllAppsList();
+ private AllAppsList mAllAppsList;
+ private IconCache mIconCache;
+
+ private Bitmap mDefaultIcon;
public interface Callbacks {
public int getCurrentWorkspaceScreen();
@@ -75,8 +85,17 @@ public class LauncherModel extends BroadcastReceiver {
public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps);
}
- LauncherModel(LauncherApplication app) {
+ LauncherModel(LauncherApplication app, IconCache iconCache) {
mApp = app;
+ mAllAppsList = new AllAppsList(iconCache);
+ mIconCache = iconCache;
+
+ mDefaultIcon = Utilities.createIconBitmap(
+ app.getPackageManager().getDefaultActivityIcon(), app);
+ }
+
+ public Bitmap getDefaultIcon() {
+ return Bitmap.createBitmap(mDefaultIcon);
}
/**
@@ -318,7 +337,7 @@ public class LauncherModel extends BroadcastReceiver {
removed = mAllAppsList.removed;
mAllAppsList.removed = new ArrayList<ApplicationInfo>();
for (ApplicationInfo info: removed) {
- AppInfoCache.remove(info.intent.getComponent());
+ mIconCache.remove(info.intent.getComponent());
}
}
if (mAllAppsList.modified.size() > 0) {
@@ -602,6 +621,8 @@ public class LauncherModel extends BroadcastReceiver {
final Context context = mContext;
final ContentResolver contentResolver = context.getContentResolver();
final PackageManager manager = context.getPackageManager();
+ final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
+ final boolean isSafeMode = manager.isSafeMode();
/* TODO
if (mLocaleChanged) {
@@ -613,6 +634,8 @@ public class LauncherModel extends BroadcastReceiver {
mAppWidgets.clear();
mFolders.clear();
+ final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
+
final Cursor c = contentResolver.query(
LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
@@ -649,7 +672,7 @@ public class LauncherModel extends BroadcastReceiver {
final int displayModeIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.DISPLAY_MODE);
- ApplicationInfo info;
+ ShortcutInfo info;
String intentDescription;
Widget widgetInfo;
LauncherAppWidgetInfo appWidgetInfo;
@@ -672,15 +695,15 @@ public class LauncherModel extends BroadcastReceiver {
}
if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = getApplicationInfo(manager, intent, context);
+ info = getShortcutInfo(manager, intent, context);
} else {
- info = getApplicationInfoShortcut(c, context, iconTypeIndex,
+ info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex);
}
if (info == null) {
- info = new ApplicationInfo();
- info.icon = manager.getDefaultActivityIcon();
+ info = new ShortcutInfo();
+ info.setIcon(getDefaultIcon());
}
if (info != null) {
@@ -734,40 +757,50 @@ public class LauncherModel extends BroadcastReceiver {
break;
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
-
id = c.getLong(idIndex);
- LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
+ Uri uri = Uri.parse(c.getString(uriIndex));
- intentDescription = c.getString(intentIndex);
- intent = null;
- if (intentDescription != null) {
- try {
- intent = Intent.parseUri(intentDescription, 0);
- } catch (URISyntaxException e) {
- // Ignore, a live folder might not have a base intent
- }
- }
-
- liveFolderInfo.title = c.getString(titleIndex);
- liveFolderInfo.id = id;
- container = c.getInt(containerIndex);
- liveFolderInfo.container = container;
- liveFolderInfo.screen = c.getInt(screenIndex);
- liveFolderInfo.cellX = c.getInt(cellXIndex);
- liveFolderInfo.cellY = c.getInt(cellYIndex);
- liveFolderInfo.uri = Uri.parse(c.getString(uriIndex));
- liveFolderInfo.baseIntent = intent;
- liveFolderInfo.displayMode = c.getInt(displayModeIndex);
-
- loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
- iconResourceIndex, liveFolderInfo);
+ // Make sure the live folder exists
+ final ProviderInfo providerInfo =
+ context.getPackageManager().resolveContentProvider(
+ uri.getAuthority(), 0);
- switch (container) {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(liveFolderInfo);
- break;
+ if (providerInfo == null && !isSafeMode) {
+ itemsToRemove.add(id);
+ } else {
+ LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
+
+ intentDescription = c.getString(intentIndex);
+ intent = null;
+ if (intentDescription != null) {
+ try {
+ intent = Intent.parseUri(intentDescription, 0);
+ } catch (URISyntaxException e) {
+ // Ignore, a live folder might not have a base intent
+ }
+ }
+
+ liveFolderInfo.title = c.getString(titleIndex);
+ liveFolderInfo.id = id;
+ liveFolderInfo.uri = uri;
+ container = c.getInt(containerIndex);
+ liveFolderInfo.container = container;
+ liveFolderInfo.screen = c.getInt(screenIndex);
+ liveFolderInfo.cellX = c.getInt(cellXIndex);
+ liveFolderInfo.cellY = c.getInt(cellYIndex);
+ liveFolderInfo.baseIntent = intent;
+ liveFolderInfo.displayMode = c.getInt(displayModeIndex);
+
+ loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
+ iconResourceIndex, liveFolderInfo);
+
+ switch (container) {
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+ mItems.add(liveFolderInfo);
+ break;
+ }
+ mFolders.put(liveFolderInfo.id, liveFolderInfo);
}
- mFolders.put(liveFolderInfo.id, liveFolderInfo);
break;
case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
@@ -792,23 +825,33 @@ public class LauncherModel extends BroadcastReceiver {
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
// Read all Launcher-specific widget details
int appWidgetId = c.getInt(appWidgetIdIndex);
- appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
- appWidgetInfo.id = c.getLong(idIndex);
- appWidgetInfo.screen = c.getInt(screenIndex);
- appWidgetInfo.cellX = c.getInt(cellXIndex);
- appWidgetInfo.cellY = c.getInt(cellYIndex);
- appWidgetInfo.spanX = c.getInt(spanXIndex);
- appWidgetInfo.spanY = c.getInt(spanYIndex);
+ id = c.getLong(idIndex);
- container = c.getInt(containerIndex);
- if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- Log.e(TAG, "Widget found where container "
- + "!= CONTAINER_DESKTOP -- ignoring!");
- continue;
+ final AppWidgetProviderInfo provider =
+ widgets.getAppWidgetInfo(appWidgetId);
+
+ if (!isSafeMode && (provider == null || provider.provider == null ||
+ provider.provider.getPackageName() == null)) {
+ itemsToRemove.add(id);
+ } else {
+ appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
+ appWidgetInfo.id = id;
+ appWidgetInfo.screen = c.getInt(screenIndex);
+ appWidgetInfo.cellX = c.getInt(cellXIndex);
+ appWidgetInfo.cellY = c.getInt(cellYIndex);
+ appWidgetInfo.spanX = c.getInt(spanXIndex);
+ appWidgetInfo.spanY = c.getInt(spanYIndex);
+
+ container = c.getInt(containerIndex);
+ if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ Log.e(TAG, "Widget found where container "
+ + "!= CONTAINER_DESKTOP -- ignoring!");
+ continue;
+ }
+ appWidgetInfo.container = c.getInt(containerIndex);
+
+ mAppWidgets.add(appWidgetInfo);
}
- appWidgetInfo.container = c.getInt(containerIndex);
-
- mAppWidgets.add(appWidgetInfo);
break;
}
} catch (Exception e) {
@@ -818,6 +861,25 @@ public class LauncherModel extends BroadcastReceiver {
} finally {
c.close();
}
+
+ if (itemsToRemove.size() > 0) {
+ ContentProviderClient client = contentResolver.acquireContentProviderClient(
+ LauncherSettings.Favorites.CONTENT_URI);
+ // Remove dead items
+ for (long id : itemsToRemove) {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "Removed id = " + id);
+ }
+ // Don't notify content observers
+ try {
+ client.delete(LauncherSettings.Favorites.getContentUri(id, false),
+ null, null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not remove id = " + id);
+ }
+ }
+ }
+
if (DEBUG_LOADERS) {
Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
}
@@ -945,9 +1007,7 @@ public class LauncherModel extends BroadcastReceiver {
return;
}
- final Context context = mContext;
- final PackageManager packageManager = context.getPackageManager();
-
+ final PackageManager packageManager = mContext.getPackageManager();
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
synchronized (mLock) {
@@ -958,10 +1018,9 @@ public class LauncherModel extends BroadcastReceiver {
long t = SystemClock.uptimeMillis();
int N = apps.size();
- Utilities.BubbleText bubble = new Utilities.BubbleText(context);
for (int i=0; i<N && !mStopped; i++) {
// This builds the icon bitmaps.
- mAllAppsList.add(AppInfoCache.cache(apps.get(i), context, bubble));
+ mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
}
Collections.sort(mAllAppsList.data, APP_NAME_COMPARATOR);
Collections.sort(mAllAppsList.added, APP_NAME_COMPARATOR);
@@ -976,7 +1035,7 @@ public class LauncherModel extends BroadcastReceiver {
private void bindAllApps() {
synchronized (mLock) {
final ArrayList<ApplicationInfo> results
- = (ArrayList<ApplicationInfo>)mAllAppsList.data.clone();
+ = (ArrayList<ApplicationInfo>) mAllAppsList.data.clone();
// We're adding this now, so clear out this so we don't re-send them.
mAllAppsList.added = new ArrayList<ApplicationInfo>();
mHandler.post(new Runnable() {
@@ -991,7 +1050,7 @@ public class LauncherModel extends BroadcastReceiver {
if (DEBUG_LOADERS) {
Log.d(TAG, "bound app " + count + " icons in "
- + (SystemClock.uptimeMillis()-t) + "ms");
+ + (SystemClock.uptimeMillis() - t) + "ms");
}
}
});
@@ -1022,9 +1081,9 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
- * Make an ApplicationInfo object for an application.
+ * Make an ShortcutInfo object for a sortcut that is an application.
*/
- private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent,
+ public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
Context context) {
final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
@@ -1032,26 +1091,26 @@ public class LauncherModel extends BroadcastReceiver {
return null;
}
- final ApplicationInfo info = new ApplicationInfo();
+ final ShortcutInfo info = new ShortcutInfo();
final ActivityInfo activityInfo = resolveInfo.activityInfo;
- info.icon = Utilities.createIconThumbnail(activityInfo.loadIcon(manager), context);
+ info.setIcon(mIconCache.getIcon(intent.getComponent(), resolveInfo));
if (info.title == null || info.title.length() == 0) {
info.title = activityInfo.loadLabel(manager);
}
if (info.title == null) {
- info.title = "";
+ info.title = activityInfo.name;
}
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
return info;
}
/**
- * Make an ApplicationInfo object for a sortcut
+ * Make an ShortcutInfo object for a shortcut that isn't an application.
*/
- private static ApplicationInfo getApplicationInfoShortcut(Cursor c, Context context,
+ private ShortcutInfo getShortcutInfo(Cursor c, Context context,
int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) {
- final ApplicationInfo info = new ApplicationInfo();
+ final ShortcutInfo info = new ShortcutInfo();
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
int iconType = c.getInt(iconTypeIndex);
@@ -1063,9 +1122,9 @@ public class LauncherModel extends BroadcastReceiver {
try {
Resources resources = packageManager.getResourcesForApplication(packageName);
final int id = resources.getIdentifier(resourceName, null, null);
- info.icon = Utilities.createIconThumbnail(resources.getDrawable(id), context);
+ info.setIcon(Utilities.createIconBitmap(resources.getDrawable(id), context));
} catch (Exception e) {
- info.icon = packageManager.getDefaultActivityIcon();
+ info.setIcon(getDefaultIcon());
}
info.iconResource = new Intent.ShortcutIconResource();
info.iconResource.packageName = packageName;
@@ -1076,23 +1135,74 @@ public class LauncherModel extends BroadcastReceiver {
byte[] data = c.getBlob(iconIndex);
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- info.icon = new FastBitmapDrawable(
- Utilities.createBitmapThumbnail(bitmap, context));
+ info.setIcon(bitmap);
} catch (Exception e) {
- packageManager = context.getPackageManager();
- info.icon = packageManager.getDefaultActivityIcon();
+ info.setIcon(getDefaultIcon());
}
- info.filtered = true;
info.customIcon = true;
break;
default:
- info.icon = context.getPackageManager().getDefaultActivityIcon();
+ info.setIcon(getDefaultIcon());
info.customIcon = false;
break;
}
return info;
}
+ ShortcutInfo addShortcut(Context context, Intent data,
+ CellLayout.CellInfo cellInfo, boolean notify) {
+
+ final ShortcutInfo info = infoFromShortcutIntent(context, data);
+ addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
+
+ return info;
+ }
+
+ private ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
+ Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+ String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+ Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
+
+ Bitmap icon = null;
+ boolean filtered = false;
+ boolean customIcon = false;
+ ShortcutIconResource iconResource = null;
+
+ if (bitmap != null && bitmap instanceof Bitmap) {
+ icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
+ filtered = true;
+ customIcon = true;
+ } else {
+ Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
+ if (extra != null && extra instanceof ShortcutIconResource) {
+ try {
+ iconResource = (ShortcutIconResource) extra;
+ final PackageManager packageManager = context.getPackageManager();
+ Resources resources = packageManager.getResourcesForApplication(
+ iconResource.packageName);
+ final int id = resources.getIdentifier(iconResource.resourceName, null, null);
+ icon = Utilities.createIconBitmap(resources.getDrawable(id), context);
+ } catch (Exception e) {
+ Log.w(TAG, "Could not load shortcut icon: " + extra);
+ }
+ }
+ }
+
+ if (icon == null) {
+ icon = getDefaultIcon();
+ }
+
+ final ShortcutInfo info = new ShortcutInfo();
+ info.setIcon(icon);
+ info.title = name;
+ info.intent = intent;
+ info.customIcon = customIcon;
+ info.iconResource = iconResource;
+
+ return info;
+ }
+
private static void loadLiveFolderIcon(Context context, Cursor c, int iconTypeIndex,
int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
@@ -1105,18 +1215,21 @@ public class LauncherModel extends BroadcastReceiver {
try {
Resources resources = packageManager.getResourcesForApplication(packageName);
final int id = resources.getIdentifier(resourceName, null, null);
- liveFolderInfo.icon = resources.getDrawable(id);
+ liveFolderInfo.icon = Utilities.createIconBitmap(resources.getDrawable(id),
+ context);
} catch (Exception e) {
- liveFolderInfo.icon =
- context.getResources().getDrawable(R.drawable.ic_launcher_folder);
+ liveFolderInfo.icon = Utilities.createIconBitmap(
+ context.getResources().getDrawable(R.drawable.ic_launcher_folder),
+ context);
}
liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
liveFolderInfo.iconResource.packageName = packageName;
liveFolderInfo.iconResource.resourceName = resourceName;
break;
default:
- liveFolderInfo.icon =
- context.getResources().getDrawable(R.drawable.ic_launcher_folder);
+ liveFolderInfo.icon = Utilities.createIconBitmap(
+ context.getResources().getDrawable(R.drawable.ic_launcher_folder),
+ context);
}
}
diff --git a/src/com/android/launcher2/LauncherProvider.java b/src/com/android/launcher2/LauncherProvider.java
index c3ceefdd3..62c19df9f 100644
--- a/src/com/android/launcher2/LauncherProvider.java
+++ b/src/com/android/launcher2/LauncherProvider.java
@@ -32,9 +32,12 @@ import android.content.pm.PackageManager;
import android.content.pm.ActivityInfo;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteStatement;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.Cursor;
import android.database.SQLException;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.util.Log;
import android.util.Xml;
import android.util.AttributeSet;
@@ -58,7 +61,7 @@ public class LauncherProvider extends ContentProvider {
private static final String DATABASE_NAME = "launcher.db";
- private static final int DATABASE_VERSION = 6;
+ private static final int DATABASE_VERSION = 8;
static final String AUTHORITY = "com.android.launcher2.settings";
@@ -382,7 +385,15 @@ public class LauncherProvider extends ContentProvider {
version = 6;
}
}
-
+
+ if (version < 8) {
+ // Version 8 (froyo) has the icons all normalized. This should
+ // already be the case in practice, but we now rely on it and don't
+ // resample the images each time.
+ normalizeIcons(db);
+ version = 8;
+ }
+
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
@@ -457,10 +468,64 @@ public class LauncherProvider extends ContentProvider {
return true;
}
+ private void normalizeIcons(SQLiteDatabase db) {
+ Log.d(TAG, "normalizing icons");
+
+ db.beginTransaction();
+ Cursor c = null;
+ try {
+ boolean logged = false;
+ final ContentValues values = new ContentValues();
+ final ContentResolver cr = mContext.getContentResolver();
+ final SQLiteStatement update = db.compileStatement("UPDATE favorites "
+ + "SET icon=? WHERE _id=?");
+
+ c = db.rawQuery("SELECT _id, icon FROM favorites WHERE iconType=" +
+ Favorites.ICON_TYPE_BITMAP, null);
+
+ final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
+ final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON);
+
+ while (c.moveToNext()) {
+ long id = c.getLong(idIndex);
+ byte[] data = c.getBlob(iconIndex);
+ try {
+ Bitmap bitmap = Utilities.resampleIconBitmap(
+ BitmapFactory.decodeByteArray(data, 0, data.length),
+ mContext);
+ if (bitmap != null) {
+ update.bindLong(1, id);
+ data = ItemInfo.flattenBitmap(bitmap);
+ if (data != null) {
+ update.bindBlob(2, data);
+ update.execute();
+ }
+ bitmap.recycle();
+ bitmap = null;
+ }
+ } catch (Exception e) {
+ if (!logged) {
+ Log.e(TAG, "Failed normalizing icon " + id, e);
+ } else {
+ Log.e(TAG, "Also failed normalizing icon " + id);
+ }
+ logged = true;
+ }
+ }
+ } catch (SQLException ex) {
+ Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
+ } finally {
+ db.endTransaction();
+ if (c != null) {
+ c.close();
+ }
+ }
+
+ }
+
/**
* Upgrade existing clock and photo frame widgets into their new widget
- * equivalents. This method allocates appWidgetIds, and then hands off to
- * LauncherAppWidgetBinder to finish the actual binding.
+ * equivalents.
*/
private void convertWidgets(SQLiteDatabase db) {
final int[] bindSources = new int[] {
diff --git a/src/com/android/launcher2/LauncherSettings.java b/src/com/android/launcher2/LauncherSettings.java
index a438d47cb..9c685ceaa 100644
--- a/src/com/android/launcher2/LauncherSettings.java
+++ b/src/com/android/launcher2/LauncherSettings.java
@@ -91,8 +91,7 @@ class LauncherSettings {
}
/**
- * Favorites. When changing these values, be sure to update
- * {@link com.android.settings.LauncherAppWidgetBinder} as needed.
+ * Favorites.
*/
static final class Favorites implements BaseLauncherColumns {
/**
diff --git a/src/com/android/launcher2/LiveFolderAdapter.java b/src/com/android/launcher2/LiveFolderAdapter.java
index b0e9eff1f..58b43e33a 100644
--- a/src/com/android/launcher2/LiveFolderAdapter.java
+++ b/src/com/android/launcher2/LiveFolderAdapter.java
@@ -141,7 +141,12 @@ class LiveFolderAdapter extends CursorAdapter {
if (icon == null) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, mContext));
+ final Bitmap resampled = Utilities.resampleIconBitmap(bitmap, mContext);
+ if (bitmap != resampled) {
+ // If we got back a different object, we don't need the old one any more.
+ bitmap.recycle();
+ }
+ icon = new FastBitmapDrawable(resampled);
mCustomIcons.put(holder.id, new SoftReference<Drawable>(icon));
}
} else if (holder.iconResourceIndex != -1 && holder.iconPackageIndex != -1) {
@@ -154,7 +159,8 @@ class LiveFolderAdapter extends CursorAdapter {
cursor.getString(holder.iconPackageIndex));
final int id = resources.getIdentifier(resource,
null, null);
- icon = Utilities.createIconThumbnail(resources.getDrawable(id), mContext);
+ icon = new FastBitmapDrawable(
+ Utilities.createIconBitmap(resources.getDrawable(id), mContext));
mIcons.put(resource, icon);
} catch (Exception e) {
// Ignore
diff --git a/src/com/android/launcher2/LiveFolderIcon.java b/src/com/android/launcher2/LiveFolderIcon.java
index 55f100cce..f80928bd4 100644
--- a/src/com/android/launcher2/LiveFolderIcon.java
+++ b/src/com/android/launcher2/LiveFolderIcon.java
@@ -21,7 +21,7 @@ import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.LayoutInflater;
-import android.graphics.drawable.Drawable;
+import android.graphics.Bitmap;
public class LiveFolderIcon extends FolderIcon {
public LiveFolderIcon(Context context, AttributeSet attrs) {
@@ -39,13 +39,12 @@ public class LiveFolderIcon extends FolderIcon {
LayoutInflater.from(launcher).inflate(resId, group, false);
final Resources resources = launcher.getResources();
- Drawable d = folderInfo.icon;
- if (d == null) {
- d = Utilities.createIconThumbnail(resources.getDrawable(R.drawable.ic_launcher_folder),
+ Bitmap b = folderInfo.icon;
+ if (b == null) {
+ b = Utilities.createIconBitmap(resources.getDrawable(R.drawable.ic_launcher_folder),
launcher);
- folderInfo.filtered = true;
}
- icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
+ icon.setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(b), null, null);
icon.setText(folderInfo.title);
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
diff --git a/src/com/android/launcher2/LiveFolderInfo.java b/src/com/android/launcher2/LiveFolderInfo.java
index 5b1217c15..7d0a0f58f 100644
--- a/src/com/android/launcher2/LiveFolderInfo.java
+++ b/src/com/android/launcher2/LiveFolderInfo.java
@@ -19,6 +19,7 @@ package com.android.launcher2;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.drawable.Drawable;
+import android.graphics.Bitmap;
import android.net.Uri;
class LiveFolderInfo extends FolderInfo {
@@ -41,12 +42,7 @@ class LiveFolderInfo extends FolderInfo {
/**
* The live folder icon.
*/
- Drawable icon;
-
- /**
- * When set to true, indicates that the icon has been resized.
- */
- boolean filtered;
+ Bitmap icon;
/**
* Reference to the live folder icon as an application's resource.
diff --git a/src/com/android/launcher2/ShortcutInfo.java b/src/com/android/launcher2/ShortcutInfo.java
new file mode 100644
index 000000000..cb73ac05b
--- /dev/null
+++ b/src/com/android/launcher2/ShortcutInfo.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Represents a launchable icon on the workspaces and in folders.
+ */
+class ShortcutInfo extends ItemInfo {
+
+ /**
+ * The application name.
+ */
+ CharSequence title;
+
+ /**
+ * The intent used to start the application.
+ */
+ Intent intent;
+
+ /**
+ * Indicates whether the icon comes from an application's resource (if false)
+ * or from a custom Bitmap (if true.)
+ */
+ boolean customIcon;
+
+ /**
+ * If isShortcut=true and customIcon=false, this contains a reference to the
+ * shortcut icon as an application's resource.
+ */
+ Intent.ShortcutIconResource iconResource;
+
+ /**
+ * The application icon.
+ */
+ private Bitmap mIcon;
+
+ ShortcutInfo() {
+ itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
+ }
+
+ public ShortcutInfo(ShortcutInfo info) {
+ super(info);
+ title = info.title.toString();
+ intent = new Intent(info.intent);
+ if (info.iconResource != null) {
+ iconResource = new Intent.ShortcutIconResource();
+ iconResource.packageName = info.iconResource.packageName;
+ iconResource.resourceName = info.iconResource.resourceName;
+ }
+ mIcon = info.mIcon; // TODO: should make a copy here. maybe we don't need this ctor at all
+ customIcon = info.customIcon;
+ }
+
+ /** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */
+ public ShortcutInfo(ApplicationInfo info) {
+ super(info);
+ title = info.title.toString();
+ intent = new Intent(info.intent);
+ customIcon = false;
+ }
+
+ public void setIcon(Bitmap b) {
+ mIcon = b;
+ }
+
+ public Bitmap getIcon(IconCache iconCache) {
+ if (mIcon == null) {
+ mIcon = iconCache.getIcon(this.intent);
+ }
+ return mIcon;
+ }
+
+ /**
+ * Creates the application intent based on a component name and various launch flags.
+ * Sets {@link #itemType} to {@link LauncherSettings.BaseLauncherColumns#ITEM_TYPE_APPLICATION}.
+ *
+ * @param className the class name of the component representing the intent
+ * @param launchFlags the launch flags
+ */
+ final void setActivity(ComponentName className, int launchFlags) {
+ intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setComponent(className);
+ intent.setFlags(launchFlags);
+ itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
+ }
+
+ @Override
+ void onAddToDatabase(ContentValues values) {
+ super.onAddToDatabase(values);
+
+ String titleStr = title != null ? title.toString() : null;
+ values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
+
+ String uri = intent != null ? intent.toUri(0) : null;
+ values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
+
+ if (customIcon) {
+ values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
+ LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
+ Bitmap bitmap = this.mIcon;
+ writeBitmap(values, bitmap);
+ } else {
+ values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
+ LauncherSettings.BaseLauncherColumns.ICON_TYPE_RESOURCE);
+ if (iconResource != null) {
+ values.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE,
+ iconResource.packageName);
+ values.put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE,
+ iconResource.resourceName);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return title.toString();
+ }
+
+ @Override
+ void unbind() {
+ super.unbind();
+ }
+
+
+ public static void dumpShortcutInfoList(String tag, String label,
+ ArrayList<ShortcutInfo> list) {
+ Log.d(tag, label + " size=" + list.size());
+ for (ShortcutInfo info: list) {
+ Log.d(tag, " title=\"" + info.title + " icon=" + info.mIcon
+ + " customIcon=" + info.customIcon);
+ }
+ }
+}
+
diff --git a/src/com/android/launcher2/ApplicationsAdapter.java b/src/com/android/launcher2/ShortcutsAdapter.java
index 129103af0..212b5d62d 100644
--- a/src/com/android/launcher2/ApplicationsAdapter.java
+++ b/src/com/android/launcher2/ShortcutsAdapter.java
@@ -29,34 +29,29 @@ import java.util.ArrayList;
/**
* GridView adapter to show the list of applications and shortcuts
*/
-public class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> {
+public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
private final LayoutInflater mInflater;
private final PackageManager mPackageManager;
+ private final IconCache mIconCache;
- public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
+ public ShortcutsAdapter(Context context, ArrayList<ShortcutInfo> apps) {
super(context, 0, apps);
mPackageManager = context.getPackageManager();
mInflater = LayoutInflater.from(context);
+ mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final ApplicationInfo info = getItem(position);
+ final ShortcutInfo info = getItem(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
}
- if (info.icon == null) {
- info.icon = AppInfoCache.getIconDrawable(mPackageManager, info);
- }
- if (!info.filtered) {
- info.icon = Utilities.createIconThumbnail(info.icon, getContext());
- info.filtered = true;
- }
-
final TextView textView = (TextView) convertView;
- textView.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
textView.setText(info.title);
return convertView;
diff --git a/src/com/android/launcher2/UserFolder.java b/src/com/android/launcher2/UserFolder.java
index 16fe6160c..148949217 100644
--- a/src/com/android/launcher2/UserFolder.java
+++ b/src/com/android/launcher2/UserFolder.java
@@ -46,13 +46,14 @@ public class UserFolder extends Folder implements DropTarget {
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
- ApplicationInfo item = (ApplicationInfo) dragInfo;
- if (item.container == NO_ID) {
+ ShortcutInfo item;
+ if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
- item = new ApplicationInfo((ApplicationInfo)item);
+ item = ((ApplicationInfo)dragInfo).makeShortcut();
+ } else {
+ item = (ShortcutInfo)dragInfo;
}
- //noinspection unchecked
- ((ArrayAdapter<ApplicationInfo>) mContent.getAdapter()).add((ApplicationInfo) dragInfo);
+ ((ShortcutsAdapter)mContent.getAdapter()).add(item);
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
}
@@ -71,16 +72,14 @@ public class UserFolder extends Folder implements DropTarget {
@Override
public void onDropCompleted(View target, boolean success) {
if (success) {
- //noinspection unchecked
- ArrayAdapter<ApplicationInfo> adapter =
- (ArrayAdapter<ApplicationInfo>) mContent.getAdapter();
+ ShortcutsAdapter adapter = (ShortcutsAdapter)mContent.getAdapter();
adapter.remove(mDragItem);
}
}
void bind(FolderInfo info) {
super.bind(info);
- setContentAdapter(new ApplicationsAdapter(mContext, ((UserFolderInfo) info).contents));
+ setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
}
// When the folder opens, we need to refresh the GridView's selection by
diff --git a/src/com/android/launcher2/UserFolderInfo.java b/src/com/android/launcher2/UserFolderInfo.java
index 75b19eec6..0b8841c10 100644
--- a/src/com/android/launcher2/UserFolderInfo.java
+++ b/src/com/android/launcher2/UserFolderInfo.java
@@ -27,7 +27,7 @@ class UserFolderInfo extends FolderInfo {
/**
* The apps and shortcuts
*/
- ArrayList<ApplicationInfo> contents = new ArrayList<ApplicationInfo>();
+ ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
UserFolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER;
@@ -38,7 +38,7 @@ class UserFolderInfo extends FolderInfo {
*
* @param item
*/
- public void add(ApplicationInfo item) {
+ public void add(ShortcutInfo item) {
contents.add(item);
}
@@ -47,7 +47,7 @@ class UserFolderInfo extends FolderInfo {
*
* @param item
*/
- public void remove(ApplicationInfo item) {
+ public void remove(ShortcutInfo item) {
contents.remove(item);
}
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index 2dfba4317..fbe489ec5 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -22,7 +22,6 @@ import android.graphics.drawable.PaintDrawable;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
-import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
@@ -52,15 +51,10 @@ final class Utilities {
private static int sIconTextureWidth = -1;
private static int sIconTextureHeight = -1;
- private static int sTitleMargin = -1;
- private static float sBlurRadius = -1;
- private static Rect sIconTextureRect;
-
private static final Paint sPaint = new Paint();
private static final Paint sBlurPaint = new Paint();
private static final Paint sGlowColorPressedPaint = new Paint();
private static final Paint sGlowColorFocusedPaint = new Paint();
- private static final Paint sEmptyPaint = new Paint();
private static final Rect sBounds = new Rect();
private static final Rect sOldBounds = new Rect();
private static final Canvas sCanvas = new Canvas();
@@ -91,87 +85,6 @@ final class Utilities {
return bitmap;
}
- /**
- * Returns a Drawable representing the thumbnail of the specified Drawable.
- * The size of the thumbnail is defined by the dimension
- * android.R.dimen.launcher_application_icon_size.
- *
- * @param icon The icon to get a thumbnail of.
- * @param context The application's context.
- *
- * @return A thumbnail for the specified icon or the icon itself if the
- * thumbnail could not be created.
- */
- static Drawable createIconThumbnail(Drawable icon, Context context) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- initStatics(context);
- }
-
- int width = sIconWidth;
- int height = sIconHeight;
-
- if (icon instanceof PaintDrawable) {
- PaintDrawable painter = (PaintDrawable) icon;
- painter.setIntrinsicWidth(width);
- painter.setIntrinsicHeight(height);
- } else if (icon instanceof BitmapDrawable) {
- // Ensure the bitmap has a density.
- BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
- Bitmap bitmap = bitmapDrawable.getBitmap();
- if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
- bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());
- }
- }
- int iconWidth = icon.getIntrinsicWidth();
- int iconHeight = icon.getIntrinsicHeight();
-
- if (iconWidth > 0 && iconHeight > 0) {
- if (width < iconWidth || height < iconHeight) {
- final float ratio = (float) iconWidth / iconHeight;
-
- if (iconWidth > iconHeight) {
- height = (int) (width / ratio);
- } else if (iconHeight > iconWidth) {
- width = (int) (height * ratio);
- }
-
- final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
- Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
- final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
- final Canvas canvas = sCanvas;
- canvas.setBitmap(thumb);
- // Copy the old bounds to restore them later
- // If we were to do oldBounds = icon.getBounds(),
- // the call to setBounds() that follows would
- // change the same instance and we would lose the
- // old bounds
- sOldBounds.set(icon.getBounds());
- final int x = (sIconWidth - width) / 2;
- final int y = (sIconHeight - height) / 2;
- icon.setBounds(x, y, x + width, y + height);
- icon.draw(canvas);
- icon.setBounds(sOldBounds);
- icon = new FastBitmapDrawable(thumb);
- } else if (iconWidth < width && iconHeight < height) {
- final Bitmap.Config c = Bitmap.Config.ARGB_8888;
- final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
- final Canvas canvas = sCanvas;
- canvas.setBitmap(thumb);
- sOldBounds.set(icon.getBounds());
- final int x = (width - iconWidth) / 2;
- final int y = (height - iconHeight) / 2;
- icon.setBounds(x, y, x + iconWidth, y + iconHeight);
- icon.draw(canvas);
- icon.setBounds(sOldBounds);
- icon = new FastBitmapDrawable(thumb);
- }
- }
-
- return icon;
- }
- }
-
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
static int sColorIndex = 0;
@@ -179,8 +92,7 @@ final class Utilities {
* Returns a bitmap suitable for the all apps view. The bitmap will be a power
* of two sized ARGB_8888 bitmap that can be used as a gl texture.
*/
- static Bitmap createAllAppsBitmap(Drawable icon, String title, BubbleText bubble,
- Context context) {
+ static Bitmap createIconBitmap(Drawable icon, Context context) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
initStatics(context);
@@ -222,8 +134,8 @@ final class Utilities {
}
// no intrinsic size --> use default size
- final int textureWidth = sIconTextureWidth;
- final int textureHeight = sIconTextureHeight;
+ int textureWidth = sIconTextureWidth;
+ int textureHeight = sIconTextureHeight;
final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
Bitmap.Config.ARGB_8888);
@@ -231,7 +143,7 @@ final class Utilities {
canvas.setBitmap(bitmap);
final int left = (textureWidth-width) / 2;
- final int top = sIconTextureRect.top;
+ final int top = (textureHeight-height) / 2;
if (false) {
// draw a big box for the icon for debugging
@@ -247,34 +159,12 @@ final class Utilities {
icon.draw(canvas);
icon.setBounds(sOldBounds);
- if (title != null) {
- bubble.drawText(canvas, title);
- }
-
return bitmap;
}
}
- static Bitmap extractIconFromTexture(Bitmap src, Context context) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- initStatics(context);
- }
- final Bitmap bitmap = Bitmap.createBitmap(sIconWidth, sIconHeight,
- Bitmap.Config.ARGB_8888);
- final Canvas canvas = sCanvas;
- canvas.setBitmap(bitmap);
-
- Rect r = new Rect(0, 0, sIconWidth, sIconHeight);
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
- canvas.drawBitmap(src, sIconTextureRect, r, sEmptyPaint);
-
- return bitmap;
- }
- }
-
- static void drawSelectedAllAppsBitmap(Canvas dest, Bitmap destBitmap,
- int destWidth, int destHeight, boolean pressed, Bitmap src) {
+ static void drawSelectedAllAppsBitmap(Canvas dest, int destWidth, int destHeight,
+ boolean pressed, Bitmap src) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
// We can't have gotten to here without src being initialized, which
@@ -284,14 +174,12 @@ final class Utilities {
}
dest.drawColor(0, PorterDuff.Mode.CLEAR);
- dest.drawBitmap(src, sIconTextureRect, sIconTextureRect, sEmptyPaint);
int[] xy = new int[2];
- Bitmap mask = destBitmap.extractAlpha(sBlurPaint, xy);
+ Bitmap mask = src.extractAlpha(sBlurPaint, xy);
float px = (destWidth - src.getWidth()) / 2;
float py = (destHeight - src.getHeight()) / 2;
- dest.drawColor(0, PorterDuff.Mode.CLEAR);
dest.drawBitmap(mask, px + xy[0], py + xy[1],
pressed ? sGlowColorPressedPaint : sGlowColorFocusedPaint);
@@ -310,55 +198,17 @@ final class Utilities {
* @return A thumbnail for the specified bitmap or the bitmap itself if the
* thumbnail could not be created.
*/
- static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context) {
+ static Bitmap resampleIconBitmap(Bitmap bitmap, Context context) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
initStatics(context);
}
- int width = sIconWidth;
- int height = sIconHeight;
-
- final int bitmapWidth = bitmap.getWidth();
- final int bitmapHeight = bitmap.getHeight();
-
- if (width > 0 && height > 0) {
- if (width < bitmapWidth || height < bitmapHeight) {
- final float ratio = (float) bitmapWidth / bitmapHeight;
-
- if (bitmapWidth > bitmapHeight) {
- height = (int) (width / ratio);
- } else if (bitmapHeight > bitmapWidth) {
- width = (int) (height * ratio);
- }
-
- final Bitmap.Config c = (width == sIconWidth && height == sIconHeight) ?
- bitmap.getConfig() : Bitmap.Config.ARGB_8888;
- final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
- final Canvas canvas = sCanvas;
- final Paint paint = sPaint;
- canvas.setBitmap(thumb);
- paint.setDither(false);
- paint.setFilterBitmap(true);
- sBounds.set((sIconWidth - width) / 2, (sIconHeight - height) / 2, width, height);
- sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
- canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
- return thumb;
- } else if (bitmapWidth < width || bitmapHeight < height) {
- final Bitmap.Config c = Bitmap.Config.ARGB_8888;
- final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
- final Canvas canvas = sCanvas;
- final Paint paint = sPaint;
- canvas.setBitmap(thumb);
- paint.setDither(false);
- paint.setFilterBitmap(true);
- canvas.drawBitmap(bitmap, (sIconWidth - bitmapWidth) / 2,
- (sIconHeight - bitmapHeight) / 2, paint);
- return thumb;
- }
+ if (bitmap.getWidth() == sIconWidth && bitmap.getHeight() == sIconHeight) {
+ return bitmap;
+ } else {
+ return createIconBitmap(new BitmapDrawable(bitmap), context);
}
-
- return bitmap;
}
}
@@ -368,13 +218,7 @@ final class Utilities {
final float density = metrics.density;
sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
- sIconTextureWidth = sIconTextureHeight = roundToPow2(sIconWidth);
-
- sTitleMargin = (int)(1 * density);
- sBlurRadius = 5 * density;
- final int left = (sIconTextureWidth-sIconWidth)/2;
- final int top = (int)(sBlurRadius) + 1;
- sIconTextureRect = new Rect(left, top, left+sIconWidth, top+sIconHeight);
+ sIconTextureWidth = sIconTextureHeight = sIconWidth + 2;
sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
sGlowColorPressedPaint.setColor(0xffffc300);
@@ -385,79 +229,75 @@ final class Utilities {
static class BubbleText {
private static final int MAX_LINES = 2;
- private TextPaint mTextPaint;
- private float mBubblePadding;
- private RectF mBubbleRect = new RectF();
+ private final TextPaint mTextPaint;
- private float mTextWidth;
- private int mLeading;
- private int mFirstLineY;
- private int mLineHeight;
+ private final float mBubblePadding;
+ private final RectF mBubbleRect = new RectF();
- private int mBitmapWidth;
- private int mBitmapHeight;
+ private final float mTextWidth;
+ private final int mLeading;
+ private final int mFirstLineY;
+ private final int mLineHeight;
- BubbleText(Context context) {
- synchronized (sCanvas) { // we share the statics :-(
- if (sIconWidth == -1) {
- initStatics(context);
- }
- final Resources resources = context.getResources();
-
- final float scale = resources.getDisplayMetrics().density;
-
- final float paddingLeft = 5.0f * scale;
- final float paddingRight = 5.0f * scale;
- final float cellWidth = resources.getDimension(R.dimen.workspace_cell_width);
- final float bubbleWidth = cellWidth - paddingLeft - paddingRight;
- mBubblePadding = 3.0f * scale;
-
- RectF bubbleRect = mBubbleRect;
- bubbleRect.left = 0;
- bubbleRect.top = 0;
- bubbleRect.right = (int)(bubbleWidth+0.5f);
-
- mTextWidth = bubbleWidth - mBubblePadding - mBubblePadding;
-
- Paint rectPaint = new Paint();
- rectPaint.setColor(0xff000000);
- rectPaint.setAntiAlias(true);
-
- TextPaint textPaint = mTextPaint = new TextPaint();
- textPaint.setTypeface(Typeface.DEFAULT);
- textPaint.setTextSize(13*scale);
- //textPaint.setColor(0xff00ff00);
- textPaint.setColor(0xffffffff);
- textPaint.setAntiAlias(true);
- if (TEXT_BURN) {
- textPaint.setShadowLayer(8, 0, 0, 0xff000000);
- }
+ private final int mBitmapWidth;
+ private final int mBitmapHeight;
+ private final int mDensity;
- final int iconTop = (int)(sBlurRadius) + 1;
- final int iconBottom = iconTop + sIconHeight;
+ BubbleText(Context context) {
+ final Resources resources = context.getResources();
+
+ final DisplayMetrics metrics = resources.getDisplayMetrics();
+ final float scale = metrics.density;
+ mDensity = metrics.densityDpi;
+
+ final float paddingLeft = 5.0f * scale;
+ final float paddingRight = 5.0f * scale;
+ final float cellWidth = resources.getDimension(R.dimen.title_texture_width);
+ final float bubbleWidth = cellWidth - paddingLeft - paddingRight;
+ mBubblePadding = 3.0f * scale;
+
+ RectF bubbleRect = mBubbleRect;
+ bubbleRect.left = 0;
+ bubbleRect.top = 0;
+ bubbleRect.right = (int) cellWidth;
+
+ mTextWidth = bubbleWidth - mBubblePadding - mBubblePadding;
+
+ TextPaint textPaint = mTextPaint = new TextPaint();
+ textPaint.setTypeface(Typeface.DEFAULT);
+ textPaint.setTextSize(13*scale);
+ textPaint.setColor(0xffffffff);
+ textPaint.setAntiAlias(true);
+ if (TEXT_BURN) {
+ textPaint.setShadowLayer(8, 0, 0, 0xff000000);
+ }
- float ascent = -textPaint.ascent();
- float descent = textPaint.descent();
- float leading = -1.0f;//(ascent+descent) * 0.1f;
- mLeading = (int)(leading + 0.5f);
- mFirstLineY = (int)(iconBottom + sTitleMargin + ascent + 0.5f);
- mLineHeight = (int)(leading + ascent + descent + 0.5f);
+ float ascent = -textPaint.ascent();
+ float descent = textPaint.descent();
+ float leading = 0.0f;//(ascent+descent) * 0.1f;
+ mLeading = (int)(leading + 0.5f);
+ mFirstLineY = (int)(leading + ascent + 0.5f);
+ mLineHeight = (int)(leading + ascent + descent + 0.5f);
- mBitmapWidth = roundToPow2((int)(mBubbleRect.width() + 0.5f));
- mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
+ mBitmapWidth = (int)(mBubbleRect.width() + 0.5f);
+ mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
- mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0);
+ mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0);
- if (false) {
- Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight="
- + mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f))
- + " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f)));
- }
+ if (false) {
+ Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight="
+ + mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f))
+ + " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f)));
}
}
- void drawText(Canvas c, String text) {
+ /** You own the bitmap after this and you must call recycle on it. */
+ Bitmap createTextBitmap(String text) {
+ Bitmap b = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ALPHA_8);
+ b.setDensity(mDensity);
+ Canvas c = new Canvas(b);
+
StaticLayout layout = new StaticLayout(text, mTextPaint, (int)mTextWidth,
Alignment.ALIGN_CENTER, 1, 0, true);
int lineCount = layout.getLineCount();
@@ -472,12 +312,14 @@ final class Utilities {
for (int i=0; i<lineCount; i++) {
//int x = (int)((mBubbleRect.width() - layout.getLineMax(i)) / 2.0f);
//int y = mFirstLineY + (i * mLineHeight);
+ final String lineText = text.substring(layout.getLineStart(i), layout.getLineEnd(i));
int x = (int)(mBubbleRect.left
- + ((mBubbleRect.width() - layout.getLineMax(i)) / 2.0f));
+ + ((mBubbleRect.width() - mTextPaint.measureText(lineText)) * 0.5f));
int y = mFirstLineY + (i * mLineHeight);
- c.drawText(text.substring(layout.getLineStart(i), layout.getLineEnd(i)),
- x, y, mTextPaint);
+ c.drawText(lineText, x, y, mTextPaint);
}
+
+ return b;
}
private int height(int lineCount) {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 9e32dd563..b93965b1c 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -17,19 +17,21 @@
package com.android.launcher2;
import android.app.WallpaperManager;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
import android.content.ComponentName;
+import android.content.pm.ProviderInfo;
import android.content.res.TypedArray;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
-import android.graphics.RectF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Parcelable;
import android.os.Parcel;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -88,6 +90,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
private OnLongClickListener mLongClickListener;
private Launcher mLauncher;
+ private IconCache mIconCache;
private DragController mDragController;
/**
@@ -103,16 +106,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
private int mTouchSlop;
private int mMaximumVelocity;
- final Rect mDrawerBounds = new Rect();
- final Rect mClipBounds = new Rect();
- int mDrawerContentHeight;
- int mDrawerContentWidth;
-
private Drawable mPreviousIndicator;
private Drawable mNextIndicator;
- private boolean mFading = true;
-
/**
* Used to inflate the Workspace from XML.
*
@@ -147,9 +143,12 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
* Initializes various states for this workspace.
*/
private void initWorkspace() {
- mScroller = new Scroller(getContext());
+ Context context = getContext();
+ mScroller = new Scroller(context);
mCurrentScreen = mDefaultScreen;
Launcher.setScreen(mCurrentScreen);
+ LauncherApplication app = (LauncherApplication)context.getApplicationContext();
+ mIconCache = app.getIconCache();
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
@@ -246,27 +245,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
/**
- * Returns how many screens there are.
- */
- int getScreenCount() {
- return getChildCount();
- }
-
- /**
- * Computes a bounding rectangle for a range of cells
- *
- * @param cellX X coordinate of upper left corner expressed as a cell position
- * @param cellY Y coordinate of upper left corner expressed as a cell position
- * @param cellHSpan Width in cells
- * @param cellVSpan Height in cells
- * @param rect Rectnagle into which to put the results
- */
- public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF rect) {
- ((CellLayout)getChildAt(mCurrentScreen)).cellToRect(cellX, cellY,
- cellHSpan, cellVSpan, rect);
- }
-
- /**
* Sets the current screen.
*
* @param currentScreen
@@ -275,6 +253,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
if (!mScroller.isFinished()) mScroller.abortAnimation();
clearVacantCache();
mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
+ mPreviousIndicator.setLevel(mCurrentScreen);
+ mNextIndicator.setLevel(mCurrentScreen);
scrollTo(mCurrentScreen * getWidth(), 0);
invalidate();
}
@@ -386,56 +366,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
mVacantCache = null;
}
}
-
- /**
- * Returns the coordinate of a vacant cell for the current screen.
- */
- boolean getVacantCell(int[] vacant, int spanX, int spanY) {
- CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
- if (group != null) {
- return group.getVacantCell(vacant, spanX, spanY);
- }
- return false;
- }
-
- /**
- * Adds the specified child in the current screen. The position and dimension of
- * the child are defined by x, y, spanX and spanY.
- *
- * @param child The child to add in one of the workspace's screens.
- * @param spanX The number of cells spanned horizontally by the child.
- * @param spanY The number of cells spanned vertically by the child.
- */
- void fitInCurrentScreen(View child, int spanX, int spanY) {
- fitInScreen(child, mCurrentScreen, spanX, spanY);
- }
-
- /**
- * Adds the specified child in the specified screen. The position and dimension of
- * the child are defined by x, y, spanX and spanY.
- *
- * @param child The child to add in one of the workspace's screens.
- * @param screen The screen in which to add the child.
- * @param spanX The number of cells spanned horizontally by the child.
- * @param spanY The number of cells spanned vertically by the child.
- */
- void fitInScreen(View child, int screen, int spanX, int spanY) {
- if (screen < 0 || screen >= getChildCount()) {
- throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount());
- }
-
- final CellLayout group = (CellLayout) getChildAt(screen);
- boolean vacant = group.getVacantCell(mTempCell, spanX, spanY);
- if (vacant) {
- group.addView(child,
- new CellLayout.LayoutParams(mTempCell[0], mTempCell[1], spanX, spanY));
- child.setHapticFeedbackEnabled(false);
- child.setOnLongClickListener(mLongClickListener);
- if (child instanceof DropTarget) {
- mDragController.addDropTarget((DropTarget)child);
- }
- }
- }
/**
* Registers the specified listener on each screen contained in this workspace.
@@ -477,60 +407,17 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
}
- public void startFading(boolean dest) {
- mFading = dest;
- invalidate();
- }
-
@Override
protected void dispatchDraw(Canvas canvas) {
- /*
- final boolean allAppsOpaque = mLauncher.isAllAppsOpaque();
- if (mFading == allAppsOpaque) {
- invalidate();
- } else {
- mFading = !allAppsOpaque;
- }
- if (allAppsOpaque) {
- // If the launcher is up, draw black.
- canvas.drawARGB(0xff, 0, 0, 0);
- return;
- }
- */
-
boolean restore = false;
int restoreCount = 0;
- // For the fade. If view gets setAlpha(), use that instead.
- float scale = mScale;
- if (scale < 0.999f) {
- int sx = mScrollX;
-
- int alpha = (scale < 0.5f) ? (int)(255 * 2 * scale) : 255;
-
- restoreCount = canvas.saveLayerAlpha(sx, 0, sx+getWidth(), getHeight(), alpha,
- Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- restore = true;
-
- if (scale < 0.999f) {
- int w = getWidth();
- w += 2 * mCurrentScreen * w;
- int dx = w/2;
- int h = getHeight();
- int dy = (h/2) - (h/4);
- canvas.translate(dx, dy);
- canvas.scale(scale, scale);
- canvas.translate(-dx, -dy);
- }
- }
-
// ViewGroup.dispatchDraw() supports many features we don't need:
// clip to padding, layout animation, animation listener, disappearing
// children, etc. The following implementation attempts to fast-track
// the drawing dispatch by drawing only what we know needs to be drawn.
- boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN
- && scale > 0.999f;
+ boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
// If we are not scrolling or flinging, draw only the current screen
if (fastDraw) {
drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
@@ -555,12 +442,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
}
- private float mScale = 1.0f;
- public void setScale(float scale) {
- mScale = scale;
- invalidate();
- }
-
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mDragController.setWindowToken(getWindowToken());
@@ -772,12 +653,14 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
case MotionEvent.ACTION_UP:
if (mTouchState != TOUCH_STATE_SCROLLING) {
-
final CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen);
if (!currentScreen.lastDownOnOccupiedCell()) {
+ getLocationOnScreen(mTempCell);
// Send a tap to the wallpaper if the last down was on empty space
mWallpaperManager.sendWallpaperCommand(getWindowToken(),
- "android.wallpaper.tap", (int) ev.getX(), (int) ev.getY(), 0, null);
+ "android.wallpaper.tap",
+ mTempCell[0] + (int) ev.getX(),
+ mTempCell[1] + (int) ev.getY(), 0, null);
}
}
@@ -970,6 +853,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
final int delta = newX - mScrollX;
final int duration = screenDelta * 300;
awakenScrollBars(duration);
+
+ if (!mScroller.isFinished()) mScroller.abortAnimation();
mScroller.startScroll(mScrollX, 0, delta, 0, duration);
invalidate();
}
@@ -1010,11 +895,11 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
}
- void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo) {
+ void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
addApplicationShortcut(info, cellInfo, false);
}
- void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo,
+ void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
boolean insertAtFirst) {
final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
final int[] result = new int[2];
@@ -1080,10 +965,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if (info.container == NO_ID) {
// Came from all apps -- make a copy
- info = new ApplicationInfo((ApplicationInfo) info);
+ info = new ShortcutInfo((ApplicationInfo)info);
}
- view = mLauncher.createShortcut(R.layout.application, cellLayout,
- (ApplicationInfo) info);
+ view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo)info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
@@ -1215,16 +1099,19 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
public void scrollLeft() {
clearVacantCache();
- if (mNextScreen == INVALID_SCREEN && mCurrentScreen > 0 && mScroller.isFinished()) {
- snapToScreen(mCurrentScreen - 1);
+ if (mScroller.isFinished()) {
+ if (mCurrentScreen > 0) snapToScreen(mCurrentScreen - 1);
+ } else {
+ if (mNextScreen > 0) snapToScreen(mNextScreen - 1);
}
}
public void scrollRight() {
clearVacantCache();
- if (mNextScreen == INVALID_SCREEN && mCurrentScreen < getChildCount() -1 &&
- mScroller.isFinished()) {
- snapToScreen(mCurrentScreen + 1);
+ if (mScroller.isFinished()) {
+ if (mCurrentScreen < getChildCount() -1) snapToScreen(mCurrentScreen + 1);
+ } else {
+ if (mNextScreen < getChildCount() -1) snapToScreen(mNextScreen + 1);
}
}
@@ -1314,74 +1201,105 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
mAllowLongPress = allowLongPress;
}
- void removeShortcutsForPackage(String packageName) {
- final ArrayList<View> childrenToRemove = new ArrayList<View>();
+ void removeItemsForPackage(final String packageName) {
final int count = getChildCount();
+ final PackageManager manager = getContext().getPackageManager();
+ final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
for (int i = 0; i < count; i++) {
final CellLayout layout = (CellLayout) getChildAt(i);
- int childCount = layout.getChildCount();
-
- childrenToRemove.clear();
- for (int j = 0; j < childCount; j++) {
- final View view = layout.getChildAt(j);
- Object tag = view.getTag();
-
- if (tag instanceof ApplicationInfo) {
- final ApplicationInfo info = (ApplicationInfo) tag;
- // We need to check for ACTION_MAIN otherwise getComponent() might
- // return null for some shortcuts (for instance, for shortcuts to
- // web pages.)
- final Intent intent = info.intent;
- final ComponentName name = intent.getComponent();
-
- if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
- name != null && packageName.equals(name.getPackageName())) {
- LauncherModel.deleteItemFromDatabase(mLauncher, info);
- childrenToRemove.add(view);
+ // Avoid ANRs by treating each screen separately
+ post(new Runnable() {
+ public void run() {
+ final ArrayList<View> childrenToRemove = new ArrayList<View>();
+ childrenToRemove.clear();
+
+ int childCount = layout.getChildCount();
+ for (int j = 0; j < childCount; j++) {
+ final View view = layout.getChildAt(j);
+ Object tag = view.getTag();
+
+ if (tag instanceof ShortcutInfo) {
+ final ShortcutInfo info = (ShortcutInfo) tag;
+ // We need to check for ACTION_MAIN otherwise getComponent() might
+ // return null for some shortcuts (for instance, for shortcuts to
+ // web pages.)
+ final Intent intent = info.intent;
+ final ComponentName name = intent.getComponent();
+
+ if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
+ name != null && packageName.equals(name.getPackageName())) {
+ // TODO: This should probably be done on a worker thread
+ LauncherModel.deleteItemFromDatabase(mLauncher, info);
+ childrenToRemove.add(view);
+ }
+ } else if (tag instanceof UserFolderInfo) {
+ final UserFolderInfo info = (UserFolderInfo) tag;
+ final ArrayList<ShortcutInfo> contents = info.contents;
+ final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
+ final int contentsCount = contents.size();
+ boolean removedFromFolder = false;
+
+ for (int k = 0; k < contentsCount; k++) {
+ final ShortcutInfo appInfo = contents.get(k);
+ final Intent intent = appInfo.intent;
+ final ComponentName name = intent.getComponent();
+
+ if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
+ name != null && packageName.equals(name.getPackageName())) {
+ toRemove.add(appInfo);
+ // TODO: This should probably be done on a worker thread
+ LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
+ removedFromFolder = true;
+ }
+ }
+
+ contents.removeAll(toRemove);
+ if (removedFromFolder) {
+ final Folder folder = getOpenFolder();
+ if (folder != null) folder.notifyDataSetChanged();
+ }
+ } else if (tag instanceof LiveFolderInfo) {
+ final LiveFolderInfo info = (LiveFolderInfo) tag;
+ final Uri uri = info.uri;
+ final ProviderInfo providerInfo = manager.resolveContentProvider(
+ uri.getAuthority(), 0);
+
+ if (providerInfo == null ||
+ packageName.equals(providerInfo.packageName)) {
+ // TODO: This should probably be done on a worker thread
+ LauncherModel.deleteItemFromDatabase(mLauncher, info);
+ childrenToRemove.add(view);
+ }
+ } else if (tag instanceof LauncherAppWidgetInfo) {
+ final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
+ final AppWidgetProviderInfo provider =
+ widgets.getAppWidgetInfo(info.appWidgetId);
+ if (provider == null ||
+ packageName.equals(provider.provider.getPackageName())) {
+ // TODO: This should probably be done on a worker thread
+ LauncherModel.deleteItemFromDatabase(mLauncher, info);
+ childrenToRemove.add(view);
+ }
+ }
}
- } else if (tag instanceof UserFolderInfo) {
- final UserFolderInfo info = (UserFolderInfo) tag;
- final ArrayList<ApplicationInfo> contents = info.contents;
- final ArrayList<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>(1);
- final int contentsCount = contents.size();
- boolean removedFromFolder = false;
-
- for (int k = 0; k < contentsCount; k++) {
- final ApplicationInfo appInfo = contents.get(k);
- final Intent intent = appInfo.intent;
- final ComponentName name = intent.getComponent();
-
- if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
- name != null && packageName.equals(name.getPackageName())) {
- toRemove.add(appInfo);
- LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
- removedFromFolder = true;
+
+ childCount = childrenToRemove.size();
+ for (int j = 0; j < childCount; j++) {
+ View child = childrenToRemove.get(j);
+ layout.removeViewInLayout(child);
+ if (child instanceof DropTarget) {
+ mDragController.removeDropTarget((DropTarget)child);
}
}
-
- contents.removeAll(toRemove);
- if (removedFromFolder) {
- final Folder folder = getOpenFolder();
- if (folder != null) folder.notifyDataSetChanged();
+
+ if (childCount > 0) {
+ layout.requestLayout();
+ layout.invalidate();
}
}
- }
-
- childCount = childrenToRemove.size();
- for (int j = 0; j < childCount; j++) {
- View child = childrenToRemove.get(j);
- layout.removeViewInLayout(child);
- if (child instanceof DropTarget) {
- mDragController.removeDropTarget((DropTarget)child);
- }
- }
-
- if (childCount > 0) {
- layout.requestLayout();
- layout.invalidate();
- }
+ });
}
}
@@ -1395,8 +1313,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
for (int j = 0; j < childCount; j++) {
final View view = layout.getChildAt(j);
Object tag = view.getTag();
- if (tag instanceof ApplicationInfo) {
- ApplicationInfo info = (ApplicationInfo) tag;
+ if (tag instanceof ShortcutInfo) {
+ ShortcutInfo info = (ShortcutInfo)tag;
// We need to check for ACTION_MAIN otherwise getComponent() might
// return null for some shortcuts (for instance, for shortcuts to
// web pages.)
@@ -1406,14 +1324,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null &&
packageName.equals(name.getPackageName())) {
- final Drawable icon = AppInfoCache.getIconDrawable(pm, info);
- if (icon != null && icon != info.icon) {
- info.icon.setCallback(null);
- info.icon = Utilities.createIconThumbnail(icon, mContext);
- info.filtered = true;
- ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
- info.icon, null, null);
- }
+ info.setIcon(mIconCache.getIcon(info.intent));
+ ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
}
}
}
@@ -1465,11 +1378,4 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
};
}
-
- void show() {
- setVisibility(VISIBLE);
- }
-
- void hide() {
- }
}