Merge "Split ApplicationInfo into ApplicationInfo which is used for AllAppsView and ShortcutInfo which is used for the workspace."
This commit is contained in:
@@ -23,8 +23,8 @@
|
||||
|
||||
launcher:cellWidth="@dimen/workspace_cell_width"
|
||||
launcher:cellHeight="@dimen/workspace_cell_height"
|
||||
launcher:longAxisStartPadding="@dimen/button_bar_height"
|
||||
launcher:longAxisEndPadding="@dimen/button_bar_height"
|
||||
launcher:longAxisStartPadding="65dip"
|
||||
launcher:longAxisEndPadding="65dip"
|
||||
launcher:shortAxisStartPadding="0dip"
|
||||
launcher:shortAxisEndPadding="0dip"
|
||||
launcher:shortAxisCells="4"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
launcher:cellWidth="@dimen/workspace_cell_width"
|
||||
launcher:cellHeight="@dimen/workspace_cell_height"
|
||||
launcher:longAxisStartPadding="0dip"
|
||||
launcher:longAxisStartPadding="8dip"
|
||||
launcher:longAxisEndPadding="@dimen/button_bar_height"
|
||||
launcher:shortAxisStartPadding="0dip"
|
||||
launcher:shortAxisEndPadding="0dip"
|
||||
|
||||
@@ -44,10 +44,13 @@ class AllAppsList {
|
||||
/** The list of apps that have been modified since the last notify() call. */
|
||||
public ArrayList<ApplicationInfo> modified = new ArrayList<ApplicationInfo>();
|
||||
|
||||
private IconCache mIconCache;
|
||||
|
||||
/**
|
||||
* Boring constructor.
|
||||
*/
|
||||
public AllAppsList() {
|
||||
public AllAppsList(IconCache iconCache) {
|
||||
mIconCache = iconCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,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);
|
||||
}
|
||||
@@ -105,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.
|
||||
*/
|
||||
@@ -122,7 +124,7 @@ class AllAppsList {
|
||||
if (packageName.equals(component.getPackageName())) {
|
||||
if (!findActivity(matches, component)) {
|
||||
removed.add(applicationInfo);
|
||||
AppInfoCache.remove(component);
|
||||
mIconCache.remove(component);
|
||||
data.remove(i);
|
||||
}
|
||||
}
|
||||
@@ -130,7 +132,6 @@ 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++) {
|
||||
final ResolveInfo info = matches.get(i);
|
||||
@@ -138,11 +139,12 @@ class AllAppsList {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,177 +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;
|
||||
}
|
||||
|
||||
application.iconBitmap = Utilities.createAllAppsBitmap(
|
||||
info.activityInfo.loadIcon(packageManager), context);
|
||||
|
||||
application.titleBitmap = bubble.createTextBitmap(application.title.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -46,49 +47,38 @@ class ApplicationInfo extends ItemInfo {
|
||||
*/
|
||||
Intent intent;
|
||||
|
||||
/**
|
||||
* The application icon.
|
||||
*/
|
||||
Drawable icon;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* If isShortcut=true and customIcon=false, this contains a reference to the
|
||||
* shortcut icon as an application's resource.
|
||||
*/
|
||||
Intent.ShortcutIconResource iconResource;
|
||||
|
||||
ApplicationInfo() {
|
||||
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must not hold the Context.
|
||||
*/
|
||||
public ApplicationInfo(ResolveInfo info, IconCache iconCache) {
|
||||
this.componentName = new ComponentName(
|
||||
info.activityInfo.applicationInfo.packageName,
|
||||
info.activityInfo.name);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,52 +96,21 @@ class ApplicationInfo extends ItemInfo {
|
||||
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 = ((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 + "\" titleBitmap=" + info.titleBitmap
|
||||
+ " icon=" + info.icon + " iconBitmap=" + info.iconBitmap
|
||||
+ " filtered=" + info.filtered + " customIcon=" + info.customIcon);
|
||||
+ " iconBitmap=" + info.iconBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
public ShortcutInfo makeShortcut() {
|
||||
return new ShortcutInfo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -67,6 +67,10 @@ class FastBitmapDrawable extends Drawable {
|
||||
return mBitmap.getHeight();
|
||||
}
|
||||
|
||||
public void setBitmap(Bitmap b) {
|
||||
mBitmap = b;
|
||||
}
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return mBitmap;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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();
|
||||
|
||||
entry.title = info.loadLabel(mPackageManager).toString();
|
||||
if (entry.title == null) {
|
||||
entry.title = info.activityInfo.name;
|
||||
}
|
||||
entry.titleBitmap = mBubble.createTextBitmap(entry.title.toString());
|
||||
entry.icon = Utilities.createIconBitmap(
|
||||
info.activityInfo.loadIcon(mPackageManager), mContext);
|
||||
|
||||
mCache.put(componentName, entry);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,6 +191,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>();
|
||||
@@ -202,7 +203,9 @@ public final class Launcher extends Activity
|
||||
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();
|
||||
|
||||
@@ -271,7 +274,7 @@ public final class Launcher extends Activity
|
||||
localeConfiguration.mnc = mnc;
|
||||
|
||||
writeConfiguration(this, localeConfiguration);
|
||||
AppInfoCache.flush();
|
||||
mIconCache.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,7 +618,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);
|
||||
}
|
||||
@@ -629,18 +632,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);
|
||||
@@ -658,39 +655,17 @@ public final class Launcher extends Activity
|
||||
cellInfo.screen = mWorkspace.getCurrentScreen();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
|
||||
final ApplicationInfo info = infoFromApplicationIntent(context, data);
|
||||
final ShortcutInfo info = mModel.getShortcutInfo(context.getPackageManager(),
|
||||
data, context);
|
||||
|
||||
if (info != null) {
|
||||
mWorkspace.addApplicationShortcut(info, cellInfo, isWorkspaceLocked());
|
||||
}
|
||||
}
|
||||
|
||||
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 |
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -703,7 +678,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);
|
||||
@@ -770,61 +745,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);
|
||||
Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
|
||||
|
||||
Drawable icon = null;
|
||||
boolean filtered = false;
|
||||
boolean customIcon = false;
|
||||
ShortcutIconResource iconResource = null;
|
||||
|
||||
if (bitmap != null && bitmap instanceof Bitmap) {
|
||||
icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail((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 = 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();
|
||||
|
||||
@@ -936,7 +856,6 @@ public final class Launcher extends Activity
|
||||
mModel.stopLoader();
|
||||
|
||||
unbindDesktopItems();
|
||||
AppInfoCache.unbindDrawables();
|
||||
|
||||
getContentResolver().unregisterContentObserver(mWidgetObserver);
|
||||
|
||||
@@ -1163,7 +1082,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);
|
||||
@@ -1185,8 +1103,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();
|
||||
@@ -1338,9 +1255,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(
|
||||
@@ -2011,7 +1928,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;
|
||||
|
||||
@@ -25,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() {
|
||||
@@ -37,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);
|
||||
@@ -79,4 +79,12 @@ public class LauncherApplication extends Application {
|
||||
mModel.initialize(launcher);
|
||||
return mModel;
|
||||
}
|
||||
|
||||
IconCache getIconCache() {
|
||||
return mIconCache;
|
||||
}
|
||||
|
||||
LauncherModel getModel() {
|
||||
return mModel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ 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;
|
||||
@@ -34,6 +35,7 @@ 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;
|
||||
@@ -65,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();
|
||||
@@ -80,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,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) {
|
||||
@@ -658,7 +672,7 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
final int displayModeIndex = c.getColumnIndexOrThrow(
|
||||
LauncherSettings.Favorites.DISPLAY_MODE);
|
||||
|
||||
ApplicationInfo info;
|
||||
ShortcutInfo info;
|
||||
String intentDescription;
|
||||
LauncherAppWidgetInfo appWidgetInfo;
|
||||
int container;
|
||||
@@ -680,15 +694,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) {
|
||||
@@ -973,9 +987,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) {
|
||||
@@ -986,10 +998,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);
|
||||
@@ -1050,9 +1061,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);
|
||||
|
||||
@@ -1060,26 +1071,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);
|
||||
@@ -1091,9 +1102,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;
|
||||
@@ -1104,23 +1115,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) {
|
||||
|
||||
@@ -1133,18 +1195,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,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;
|
||||
@@ -61,7 +64,7 @@ public class LauncherProvider extends ContentProvider {
|
||||
|
||||
private static final String DATABASE_NAME = "launcher.db";
|
||||
|
||||
private static final int DATABASE_VERSION = 7;
|
||||
private static final int DATABASE_VERSION = 8;
|
||||
|
||||
static final String AUTHORITY = "com.android.launcher2.settings";
|
||||
|
||||
@@ -392,6 +395,14 @@ public class LauncherProvider extends ContentProvider {
|
||||
version = 7;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -466,6 +477,60 @@ public class LauncherProvider extends ContentProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void normalizeIcons(SQLiteDatabase db) {
|
||||
Log.d(TAG, "normalizing icons");
|
||||
|
||||
Cursor c = null;
|
||||
try {
|
||||
boolean logged = false;
|
||||
final ContentValues values = new ContentValues();
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
final SQLiteStatement update = db.compileStatement("UPDATE favorites "
|
||||
+ "WHERE _id=? SET icon=?");
|
||||
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-12
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,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;
|
||||
|
||||
@@ -173,7 +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, Context context) {
|
||||
static Bitmap createIconBitmap(Drawable icon, Context context) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
initStatics(context);
|
||||
@@ -279,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
private OnLongClickListener mLongClickListener;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private IconCache mIconCache;
|
||||
private DragController mDragController;
|
||||
|
||||
/**
|
||||
@@ -142,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();
|
||||
@@ -880,11 +884,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];
|
||||
@@ -950,10 +954,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((ShortcutInfo)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,
|
||||
@@ -1183,8 +1186,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
final View view = layout.getChildAt(j);
|
||||
Object tag = view.getTag();
|
||||
|
||||
if (tag instanceof ApplicationInfo) {
|
||||
final ApplicationInfo info = (ApplicationInfo) tag;
|
||||
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.)
|
||||
@@ -1199,14 +1202,13 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
}
|
||||
} 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 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 ApplicationInfo appInfo = contents.get(k);
|
||||
final ShortcutInfo appInfo = contents.get(k);
|
||||
final Intent intent = appInfo.intent;
|
||||
final ComponentName name = intent.getComponent();
|
||||
|
||||
@@ -1277,8 +1279,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.)
|
||||
@@ -1288,14 +1290,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user