Redo the launcher loading code and put the real app icons into rollo.
This commit is contained in:
parent
02e638e6bf
commit
9c1289cb3b
|
@ -19,7 +19,10 @@
|
|||
#define STATE_FLING_TIME 2
|
||||
#define STATE_FLING_VELOCITY_X 3
|
||||
#define STATE_ADJUSTED_DECELERATION 4
|
||||
#define STATE_CURRENT_SCROLL_X 5 /* with fling offset applied */
|
||||
|
||||
/* with fling offset applied */
|
||||
#define STATE_CURRENT_SCROLL_X 5
|
||||
|
||||
#define STATE_FLING_DURATION 6
|
||||
#define STATE_FLING_END_POS 7
|
||||
|
||||
|
@ -36,6 +39,7 @@
|
|||
#define PAGE_PADDING_TOP_PX 80
|
||||
#define CELL_PADDING_TOP_PX 5
|
||||
#define ICON_HEIGHT_PX 64
|
||||
#define ICON_TEXTURE_HEIGHT_PX 128
|
||||
#define ICON_LABEL_GUTTER_PX 5
|
||||
#define CELL_PADDING_BOTTOM_PX 5
|
||||
#define ROW_GUTTER_PX 10
|
||||
|
@ -43,6 +47,7 @@
|
|||
#define PAGE_PADDING_LEFT_PX 22
|
||||
#define CELL_WIDTH_PX 105
|
||||
#define ICON_WIDTH_PX 64
|
||||
#define ICON_TEXTURE_WIDTH_PX 128
|
||||
#define COLUMN_GUTTER_PX 5
|
||||
#define LABEL_WIDTH_PX 105
|
||||
|
||||
|
@ -88,11 +93,14 @@ main(int launchID)
|
|||
+ CELL_PADDING_BOTTOM_PX + ROW_GUTTER_PX) * densityScale;
|
||||
float cellPaddingTop = CELL_PADDING_TOP_PX * densityScale;
|
||||
float iconHeight = ICON_HEIGHT_PX * densityScale;
|
||||
float iconTextureHeight = ICON_HEIGHT_PX / ((float)ICON_TEXTURE_HEIGHT_PX);
|
||||
float iconLabelGutter = ICON_LABEL_GUTTER_PX * densityScale;
|
||||
|
||||
float pagePaddingLeft = PAGE_PADDING_LEFT_PX * densityScale;
|
||||
float cellWidth = CELL_WIDTH_PX * densityScale;
|
||||
|
||||
float iconWidth = ICON_WIDTH_PX * densityScale;
|
||||
float iconTextureWidth = ICON_WIDTH_PX / ((float)ICON_TEXTURE_WIDTH_PX);
|
||||
float columnGutter = COLUMN_GUTTER_PX * densityScale;
|
||||
|
||||
float labelWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_WIDTH) * densityScale;
|
||||
|
@ -128,6 +136,17 @@ main(int launchID)
|
|||
} else {
|
||||
deceleration = 1000;
|
||||
}
|
||||
// minimum velocity
|
||||
if (flingVelocityPxMs < 0) {
|
||||
if (flingVelocityPxMs > -500) {
|
||||
flingVelocityPxMs = -500;
|
||||
}
|
||||
} else {
|
||||
if (flingVelocityPxMs < 500) {
|
||||
flingVelocityPxMs = 500;
|
||||
}
|
||||
}
|
||||
|
||||
// v' = v + at --> t = -v / a
|
||||
// x' = x + vt + .5 a t^2
|
||||
flingDurationMs = - flingVelocityPxMs / deceleration;
|
||||
|
@ -142,26 +161,27 @@ main(int launchID)
|
|||
}
|
||||
float scrollOnPage = modf(endPos, SCREEN_WIDTH);
|
||||
int endPage = -endPos/SCREEN_WIDTH;
|
||||
|
||||
if (flingVelocityPxMs < 0) {
|
||||
if (scrollOnPage < (SCREEN_WIDTH/2)) {
|
||||
// adjust the deceleration so we align on the page boundary
|
||||
// a = 2(x-x0-v0t)/t^2
|
||||
endPos = -(endPage+1) * SCREEN_WIDTH;
|
||||
debugI32("endPos case", 1);
|
||||
debugI32("endPos case 1", endPos);
|
||||
} else {
|
||||
// TODO: bounce
|
||||
endPos = -(endPage+1) * SCREEN_WIDTH;
|
||||
debugI32("endPos case", 2);
|
||||
debugI32("endPos case 2", endPos);
|
||||
}
|
||||
} else {
|
||||
if (scrollOnPage >= (SCREEN_WIDTH/2)) {
|
||||
// adjust the deceleration so we align on the page boundary
|
||||
endPos = -endPage * SCREEN_WIDTH;
|
||||
debugI32("endPos case", 3);
|
||||
debugI32("endPos case 3", endPos);
|
||||
} else {
|
||||
// TODO: bounce
|
||||
endPos = -endPage * SCREEN_WIDTH;
|
||||
debugI32("endPos case", 4);
|
||||
debugI32("endPos case 4", endPos);
|
||||
}
|
||||
}
|
||||
// v = v0 + at --> (v - v0) / t
|
||||
|
@ -213,18 +233,10 @@ main(int launchID)
|
|||
int currentPage = current_page(scrollXPx);
|
||||
float screenWidth = SCREEN_WIDTH * densityScale;
|
||||
|
||||
float pageLeft = -1 + ((currentPage-1)*screenWidth);
|
||||
int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
|
||||
int icon = (currentPage-1) * iconsPerPage;
|
||||
if (icon < 0) {
|
||||
icon = 0;
|
||||
}
|
||||
int page;
|
||||
int lastIcon = icon + (iconsPerPage*3);
|
||||
if (lastIcon >= iconCount) {
|
||||
lastIcon = iconCount-1;
|
||||
}
|
||||
pageLeft += scrollXPx * densityScale;
|
||||
int icon = 0;
|
||||
int lastIcon = iconCount-1;
|
||||
float pageLeft = -1 + (scrollXPx * densityScale);
|
||||
while (icon <= lastIcon) {
|
||||
// Bug makes 1.0f alpha fail.
|
||||
color(1.0f, 1.0f, 1.0f, 0.99f);
|
||||
|
@ -246,11 +258,16 @@ main(int launchID)
|
|||
bindProgramFragmentStore(NAMED_PFS);
|
||||
|
||||
bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
|
||||
drawRect(iconLeft, iconTop, iconRight, iconBottom, 0.0f);
|
||||
//drawRect(iconLeft, iconTop, iconRight, iconBottom, 0.0f);
|
||||
drawQuadTexCoords(
|
||||
iconLeft, iconTop, 0.0f, 0.0f, 0.0f,
|
||||
iconRight, iconTop, 0.0f, iconTextureWidth, 0.0f,
|
||||
iconRight, iconBottom, 0.0f, iconTextureWidth, iconTextureHeight,
|
||||
iconLeft, iconBottom, 0.0f, 0.0f, iconTextureHeight);
|
||||
|
||||
// label
|
||||
float labelLeft = s + ((cellWidth-labelWidth)/2.0f);
|
||||
float labelTop = iconBottom - iconLabelGutter;
|
||||
float labelTop = iconTop - iconHeight - iconLabelGutter;
|
||||
|
||||
bindProgramFragment(NAMED_PFText);
|
||||
bindProgramFragmentStore(NAMED_PFSText);
|
||||
|
|
|
@ -402,4 +402,4 @@ public class ActivityPicker extends AlertActivity implements
|
|||
return icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* 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.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;
|
||||
|
||||
|
||||
/**
|
||||
* Stores the list of all applications for the all apps view.
|
||||
*/
|
||||
class AllAppsList {
|
||||
public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
|
||||
|
||||
/** The list off all apps. */
|
||||
public ArrayList<ApplicationInfo> data = new ArrayList(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);
|
||||
/** The list of apps that have been removed since the last notify() call. */
|
||||
public ArrayList<ApplicationInfo> removed = new ArrayList();
|
||||
/** The list of apps that have been modified since the last notify() call. */
|
||||
public ArrayList<ApplicationInfo> modified = new ArrayList();
|
||||
|
||||
/**
|
||||
* Boring constructor.
|
||||
*/
|
||||
public AllAppsList() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the supplied ApplicationInfo objects to the list, and enqueue it into the
|
||||
* list to broadcast when notify() is called.
|
||||
*/
|
||||
public void add(ApplicationInfo info) {
|
||||
data.add(info);
|
||||
added.add(info);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
data.clear();
|
||||
// TODO: do we clear these too?
|
||||
added.clear();
|
||||
removed.clear();
|
||||
modified.clear();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
public ApplicationInfo get(int index) {
|
||||
return data.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the icons for the supplied apk called packageName.
|
||||
*/
|
||||
public void addPackage(Context context, String packageName) {
|
||||
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);
|
||||
data.add(item);
|
||||
added.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the apps for the given apk identified by packageName.
|
||||
*/
|
||||
public void removePackage(String packageName) {
|
||||
final List<ApplicationInfo> data = this.data;
|
||||
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())) {
|
||||
removed.add(info);
|
||||
data.remove(i);
|
||||
}
|
||||
}
|
||||
// This is more aggressive than it needs to be.
|
||||
AppInfoCache.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and remove icons for this package which has been updated.
|
||||
*/
|
||||
public void updatePackage(Context context, String packageName) {
|
||||
final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
|
||||
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--) {
|
||||
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);
|
||||
data.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
ApplicationInfo applicationInfo = findApplicationInfoLocked(
|
||||
info.activityInfo.applicationInfo.packageName,
|
||||
info.activityInfo.name);
|
||||
if (applicationInfo == null) {
|
||||
applicationInfo = AppInfoCache.cache(info, context, bubble);
|
||||
data.add(applicationInfo);
|
||||
added.add(applicationInfo);
|
||||
} else {
|
||||
AppInfoCache.update(info, applicationInfo, context);
|
||||
modified.add(applicationInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the package manager for MAIN/LAUNCHER activities in the supplied package.
|
||||
*/
|
||||
private static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
|
||||
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
|
||||
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
|
||||
final List<ResolveInfo> matches = new ArrayList<ResolveInfo>();
|
||||
|
||||
if (apps != null) {
|
||||
// Find all activities that match the packageName
|
||||
int count = apps.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final ResolveInfo info = apps.get(i);
|
||||
final ActivityInfo activityInfo = info.activityInfo;
|
||||
if (packageName.equals(activityInfo.packageName)) {
|
||||
matches.add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether <em>apps</em> contains <em>component</em>.
|
||||
*/
|
||||
private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
|
||||
final String className = component.getClassName();
|
||||
for (ResolveInfo info : apps) {
|
||||
final ActivityInfo activityInfo = info.activityInfo;
|
||||
if (activityInfo.name.equals(className)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ApplicationInfo object for the given packageName and className.
|
||||
*/
|
||||
private ApplicationInfo findApplicationInfoLocked(String packageName, String className) {
|
||||
for (ApplicationInfo info: data) {
|
||||
final ComponentName component = info.intent.getComponent();
|
||||
if (packageName.equals(component.getPackageName())
|
||||
&& className.equals(component.getClassName())) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -59,8 +59,11 @@ import android.graphics.PixelFormat;
|
|||
|
||||
|
||||
public class AllAppsView extends RSSurfaceView {
|
||||
private static final String TAG = "Launcher.AllAppsView";
|
||||
|
||||
private RenderScript mRS;
|
||||
private RolloRS mRollo;
|
||||
private ArrayList<ApplicationInfo> mAllAppsList;
|
||||
|
||||
private ViewConfiguration mConfig;
|
||||
private VelocityTracker mVelocity;
|
||||
|
@ -97,6 +100,9 @@ public class AllAppsView extends RSSurfaceView {
|
|||
mRS = createRenderScript();
|
||||
mRollo = new RolloRS();
|
||||
mRollo.init(getResources(), w, h);
|
||||
if (mAllAppsList != null) {
|
||||
mRollo.setApps(mAllAppsList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -109,7 +115,6 @@ public class AllAppsView extends RSSurfaceView {
|
|||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev)
|
||||
{
|
||||
Log.d(Launcher.LOG_TAG, "onTouchEvent " + ev);
|
||||
int x = (int)ev.getX();
|
||||
int deltaX;
|
||||
switch (ev.getAction()) {
|
||||
|
@ -163,10 +168,17 @@ public class AllAppsView extends RSSurfaceView {
|
|||
|
||||
DataSetObserver mIconObserver = new DataSetObserver() {
|
||||
public void onChanged() {
|
||||
Log.d(Launcher.LOG_TAG, "new icons arrived! now have " + mAdapter.getCount());
|
||||
Log.d(TAG, "new icons arrived! now have " + mAdapter.getCount());
|
||||
}
|
||||
};
|
||||
|
||||
public void setApps(ArrayList<ApplicationInfo> list) {
|
||||
mAllAppsList = list;
|
||||
if (mRollo != null) {
|
||||
mRollo.setApps(list);
|
||||
}
|
||||
}
|
||||
|
||||
public class RolloRS {
|
||||
|
||||
// Allocations ======
|
||||
|
@ -316,22 +328,9 @@ public class AllAppsView extends RSSurfaceView {
|
|||
}
|
||||
|
||||
private void initData() {
|
||||
final int count = 100;
|
||||
mParams = new Params(mRS);
|
||||
mState = new State(mRS);
|
||||
|
||||
mIcons = new Allocation[count];
|
||||
mAllocIconIDBuf = new int[count];
|
||||
mAllocIconID = Allocation.createSized(mRS,
|
||||
Element.USER_I32, mAllocIconIDBuf.length);
|
||||
|
||||
mLabels = new Allocation[count];
|
||||
mAllocLabelIDBuf = new int[mLabels.length];
|
||||
mAllocLabelID = Allocation.createSized(mRS,
|
||||
Element.USER_I32, mLabels.length);
|
||||
|
||||
Element ie8888 = Element.RGBA_8888;
|
||||
|
||||
final Utilities.BubbleText bubble = new Utilities.BubbleText(getContext());
|
||||
|
||||
mParams.bubbleWidth = bubble.getBubbleWidth();
|
||||
|
@ -339,25 +338,10 @@ public class AllAppsView extends RSSurfaceView {
|
|||
mParams.bubbleBitmapWidth = bubble.getBitmapWidth();
|
||||
mParams.bubbleBitmapHeight = bubble.getBitmapHeight();
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
mIcons[i] = Allocation.createFromBitmapResource(
|
||||
mRS, mRes, R.raw.maps, ie8888, true);
|
||||
mLabels[i] = makeTextBitmap(bubble, i%9==0 ? "Google Maps" : "Maps");
|
||||
}
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
mIcons[i].uploadToTexture(0);
|
||||
mLabels[i].uploadToTexture(0);
|
||||
mAllocIconIDBuf[i] = mIcons[i].getID();
|
||||
mAllocLabelIDBuf[i] = mLabels[i].getID();
|
||||
}
|
||||
mAllocIconID.data(mAllocIconIDBuf);
|
||||
mAllocLabelID.data(mAllocLabelIDBuf);
|
||||
|
||||
mState.iconCount = count;
|
||||
|
||||
mParams.save();
|
||||
mState.save();
|
||||
|
||||
setApps(null);
|
||||
}
|
||||
|
||||
Allocation makeTextBitmap(Utilities.BubbleText bubble, String label) {
|
||||
|
@ -383,8 +367,51 @@ public class AllAppsView extends RSSurfaceView {
|
|||
|
||||
mRS.contextBindRootScript(mScript);
|
||||
}
|
||||
}
|
||||
|
||||
private void setApps(ArrayList<ApplicationInfo> list) {
|
||||
final int count = list != null ? list.size() : 0;
|
||||
mIcons = new Allocation[count];
|
||||
mAllocIconIDBuf = new int[count];
|
||||
mAllocIconID = Allocation.createSized(mRS, Element.USER_I32, count);
|
||||
|
||||
mLabels = new Allocation[count];
|
||||
mAllocLabelIDBuf = new int[count];
|
||||
mAllocLabelID = Allocation.createSized(mRS, Element.USER_I32, count);
|
||||
|
||||
Element ie8888 = Element.RGBA_8888;
|
||||
|
||||
Utilities.BubbleText bubble = new Utilities.BubbleText(getContext());
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
final ApplicationInfo item = list.get(i);
|
||||
|
||||
mIcons[i] = Allocation.createFromBitmap(mRS, item.iconBitmap,
|
||||
Element.RGBA_8888, true);
|
||||
mLabels[i] = Allocation.createFromBitmap(mRS, item.titleBitmap,
|
||||
Element.RGBA_8888, true);
|
||||
|
||||
mIcons[i].uploadToTexture(0);
|
||||
mLabels[i].uploadToTexture(0);
|
||||
|
||||
mAllocIconIDBuf[i] = mIcons[i].getID();
|
||||
mAllocLabelIDBuf[i] = mLabels[i].getID();
|
||||
}
|
||||
|
||||
mAllocIconID.data(mAllocIconIDBuf);
|
||||
mAllocLabelID.data(mAllocLabelIDBuf);
|
||||
|
||||
mState.iconCount = count;
|
||||
|
||||
Log.d("AllAppsView", "mScript=" + mScript + " mAllocIconID=" + mAllocIconID);
|
||||
|
||||
if (mScript != null) { // wtf
|
||||
mScript.bindAllocation(mAllocIconID, Defines.ALLOC_ICON_IDS);
|
||||
mScript.bindAllocation(mAllocLabelID, Defines.ALLOC_LABEL_IDS);
|
||||
}
|
||||
|
||||
mState.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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) {
|
||||
synchronized (sCache) {
|
||||
updateTitleAndIcon(info, applicationInfo, context, new Utilities.BubbleText(context));
|
||||
|
||||
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) {
|
||||
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()) {
|
||||
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;
|
||||
}
|
||||
|
||||
Drawable icon = Utilities.createIconThumbnail(info.activityInfo.loadIcon(packageManager),
|
||||
context, true);
|
||||
application.iconBitmap = ((FastBitmapDrawable)icon).getBitmap();
|
||||
application.filtered = true;
|
||||
|
||||
application.titleBitmap = bubble.createTextBitmap(application.title.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,11 @@ class ApplicationInfo extends ItemInfo {
|
|||
*/
|
||||
CharSequence title;
|
||||
|
||||
/**
|
||||
* A bitmap of the application's text in the bubble.
|
||||
*/
|
||||
Bitmap titleBitmap;
|
||||
|
||||
/**
|
||||
* The intent used to start the application.
|
||||
*/
|
||||
|
@ -43,6 +48,11 @@ class ApplicationInfo extends ItemInfo {
|
|||
*/
|
||||
Drawable icon;
|
||||
|
||||
/**
|
||||
* A bitmap version of the application icon.
|
||||
*/
|
||||
Bitmap iconBitmap;
|
||||
|
||||
/**
|
||||
* When set to true, indicates that the icon has been resized.
|
||||
*/
|
||||
|
@ -124,4 +134,10 @@ class ApplicationInfo extends ItemInfo {
|
|||
public String toString() {
|
||||
return title.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
void unbind() {
|
||||
super.unbind();
|
||||
icon.setCallback(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.ArrayList;
|
|||
/**
|
||||
* GridView adapter to show the list of applications and shortcuts
|
||||
*/
|
||||
public class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> {
|
||||
public class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> {
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps) {
|
||||
|
@ -45,7 +45,7 @@ public class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> {
|
|||
}
|
||||
|
||||
if (!info.filtered) {
|
||||
info.icon = Utilities.createIconThumbnail(info.icon, getContext());
|
||||
info.icon = Utilities.createIconThumbnail(info.icon, getContext(), false);
|
||||
info.filtered = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ public class BubbleTextView extends TextView {
|
|||
setFocusable(true);
|
||||
mBackground = getBackground();
|
||||
setBackgroundDrawable(null);
|
||||
mBackground.setCallback(this);
|
||||
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mPaint.setColor(getContext().getResources().getColor(R.color.bubble_dark_background));
|
||||
|
@ -131,4 +130,16 @@ public class BubbleTextView extends TextView {
|
|||
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mBackground.setCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mBackground.setCallback(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.MessageQueue;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Queue of things to run on a looper thread. Items posted with {@link #post} will not
|
||||
* be actually enqued on the handler until after the last one has run, to keep from
|
||||
* starving the thread.
|
||||
*
|
||||
* This class is fifo.
|
||||
*/
|
||||
public class DeferredHandler {
|
||||
private LinkedList<Runnable> mQueue = new LinkedList();
|
||||
private MessageQueue mMessageQueue = Looper.myQueue();
|
||||
private Impl mHandler = new Impl();
|
||||
|
||||
private class Impl extends Handler implements MessageQueue.IdleHandler {
|
||||
public void handleMessage(Message msg) {
|
||||
Runnable r;
|
||||
synchronized (mQueue) {
|
||||
r = mQueue.removeFirst();
|
||||
}
|
||||
r.run();
|
||||
synchronized (mQueue) {
|
||||
scheduleNextLocked();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean queueIdle() {
|
||||
handleMessage(null);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class IdleRunnable implements Runnable {
|
||||
Runnable mRunnable;
|
||||
|
||||
IdleRunnable(Runnable r) {
|
||||
mRunnable = r;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
mRunnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
public DeferredHandler() {
|
||||
}
|
||||
|
||||
/** Schedule runnable to run after everything that's on the queue right now. */
|
||||
public void post(Runnable runnable) {
|
||||
synchronized (mQueue) {
|
||||
mQueue.add(runnable);
|
||||
if (mQueue.size() == 1) {
|
||||
scheduleNextLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Schedule runnable to run when the queue goes idle. */
|
||||
public void postIdle(final Runnable runnable) {
|
||||
post(new IdleRunnable(runnable));
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
synchronized (mQueue) {
|
||||
mQueue.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void scheduleNextLocked() {
|
||||
if (mQueue.size() > 0) {
|
||||
Runnable peek = mQueue.getFirst();
|
||||
if (peek instanceof IdleRunnable) {
|
||||
mMessageQueue.addIdleHandler(mHandler);
|
||||
} else {
|
||||
mHandler.sendEmptyMessage(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,24 +93,23 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
|
|||
|
||||
if (item.container == -1) return;
|
||||
|
||||
final LauncherModel model = Launcher.getModel();
|
||||
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||
if (item instanceof LauncherAppWidgetInfo) {
|
||||
model.removeDesktopAppWidget((LauncherAppWidgetInfo) item);
|
||||
} else {
|
||||
model.removeDesktopItem(item);
|
||||
mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
|
||||
}
|
||||
} else {
|
||||
if (source instanceof UserFolder) {
|
||||
final UserFolder userFolder = (UserFolder) source;
|
||||
final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();
|
||||
model.removeUserFolderItem(userFolderInfo, item);
|
||||
// item must be an ApplicationInfo otherwise it couldn't have been in the folder
|
||||
// in the first place.
|
||||
userFolderInfo.remove((ApplicationInfo)item);
|
||||
}
|
||||
}
|
||||
if (item instanceof UserFolderInfo) {
|
||||
final UserFolderInfo userFolderInfo = (UserFolderInfo)item;
|
||||
LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo);
|
||||
model.removeUserFolder(userFolderInfo);
|
||||
mLauncher.removeFolder(userFolderInfo);
|
||||
} else if (item instanceof LauncherAppWidgetInfo) {
|
||||
final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
|
||||
final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
|
||||
|
|
|
@ -273,8 +273,10 @@ public class DragController {
|
|||
* Call this from a drag source view.
|
||||
*/
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
Log.d(Launcher.LOG_TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging="
|
||||
+ mDragging);
|
||||
if (false) {
|
||||
Log.d(Launcher.LOG_TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging="
|
||||
+ mDragging);
|
||||
}
|
||||
final int action = ev.getAction();
|
||||
|
||||
final float screenX = ev.getRawX();
|
||||
|
|
|
@ -48,7 +48,7 @@ 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);
|
||||
d = Utilities.createIconThumbnail(d, launcher, false);
|
||||
icon.mCloseIcon = d;
|
||||
icon.mOpenIcon = resources.getDrawable(R.drawable.ic_launcher_folder_open);
|
||||
icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
|
||||
|
|
|
@ -130,4 +130,6 @@ class ItemInfo {
|
|||
}
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -50,4 +50,11 @@ class LauncherAppWidgetInfo extends ItemInfo {
|
|||
public String toString() {
|
||||
return Integer.toString(appWidgetId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void unbind() {
|
||||
super.unbind();
|
||||
hostView = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,74 @@
|
|||
package com.android.launcher2;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
public class LauncherApplication extends Application {
|
||||
public static final LauncherModel sModel = new LauncherModel();
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024);
|
||||
|
||||
super.onCreate();
|
||||
|
||||
// Register intent receivers
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
filter.addDataScheme("package");
|
||||
registerReceiver(mApplicationsReceiver, filter);
|
||||
|
||||
// Register for changes to the favorites
|
||||
ContentResolver resolver = getContentResolver();
|
||||
resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
|
||||
mFavoritesObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* There's no guarantee that this function is ever called.
|
||||
*/
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
|
||||
unregisterReceiver(mApplicationsReceiver);
|
||||
|
||||
ContentResolver resolver = getContentResolver();
|
||||
resolver.unregisterContentObserver(mFavoritesObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives notifications when applications are added/removed.
|
||||
*/
|
||||
private final BroadcastReceiver mApplicationsReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
sModel.onReceiveIntent(LauncherApplication.this, intent);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Receives notifications whenever the user favorites have changed.
|
||||
*/
|
||||
private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
// TODO: lockAllApps();
|
||||
sModel.setWorkspaceDirty();
|
||||
sModel.startLoader(LauncherApplication.this, false);
|
||||
}
|
||||
};
|
||||
|
||||
LauncherModel setLauncher(Launcher launcher) {
|
||||
sModel.initialize(launcher);
|
||||
return sModel;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -154,7 +154,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 = Utilities.createIconThumbnail(resources.getDrawable(id), mContext,
|
||||
false);
|
||||
mIcons.put(resource, icon);
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
|
|
|
@ -41,8 +41,8 @@ public class LiveFolderIcon extends FolderIcon {
|
|||
final Resources resources = launcher.getResources();
|
||||
Drawable d = folderInfo.icon;
|
||||
if (d == null) {
|
||||
d = Utilities.createIconThumbnail(
|
||||
resources.getDrawable(R.drawable.ic_launcher_folder), launcher);
|
||||
d = Utilities.createIconThumbnail(resources.getDrawable(R.drawable.ic_launcher_folder),
|
||||
launcher, false);
|
||||
folderInfo.filtered = true;
|
||||
}
|
||||
icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
|
||||
|
|
|
@ -43,7 +43,7 @@ class UserFolderInfo extends FolderInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove an app or shortcut
|
||||
* Remove an app or shortcut. Does not change the DB.
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
|
|
|
@ -78,82 +78,101 @@ final class Utilities {
|
|||
* 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.
|
||||
* @param context The application's context.
|
||||
* @param forceBitmap If this is true, the drawable will always be redrawn
|
||||
* into a new bitmap if it isn't already a BitmapDrawable or a
|
||||
* FastBitmapDrawable.
|
||||
*
|
||||
* @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) {
|
||||
if (sIconWidth == -1) {
|
||||
final Resources resources = context.getResources();
|
||||
sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
|
||||
}
|
||||
|
||||
int width = sIconWidth;
|
||||
int height = sIconHeight;
|
||||
|
||||
float scale = 1.0f;
|
||||
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());
|
||||
static Drawable createIconThumbnail(Drawable icon, Context context, boolean forceBitmap) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
final Resources resources = context.getResources();
|
||||
sIconWidth = (int)resources.getDimension(android.R.dimen.app_icon_size);
|
||||
sIconHeight = sIconWidth;
|
||||
}
|
||||
}
|
||||
int iconWidth = icon.getIntrinsicWidth();
|
||||
int iconHeight = icon.getIntrinsicHeight();
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
if (width < iconWidth || height < iconHeight || scale != 1.0f) {
|
||||
final float ratio = (float) iconWidth / iconHeight;
|
||||
int width = sIconWidth;
|
||||
int height = sIconHeight;
|
||||
|
||||
if (iconWidth > iconHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (iconHeight > iconWidth) {
|
||||
width = (int) (height * ratio);
|
||||
float scale = 1.0f;
|
||||
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();
|
||||
|
||||
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) {
|
||||
if (iconWidth > 0 && iconWidth > 0) {
|
||||
if (width < iconWidth || height < iconHeight || scale != 1.0f) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (forceBitmap) {
|
||||
// no intrinsic size --> use default size
|
||||
int w = sIconWidth;
|
||||
int h = sIconHeight;
|
||||
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
|
||||
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
|
||||
final Bitmap thumb = Bitmap.createBitmap(roundToPow2(w), roundToPow2(h), 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.setBounds(0, 0, w, h);
|
||||
icon.draw(canvas);
|
||||
icon.setBounds(sOldBounds);
|
||||
icon = new FastBitmapDrawable(thumb);
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,8 +180,6 @@ final class Utilities {
|
|||
* 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 bitmap The bitmap to get a thumbnail of.
|
||||
* @param context The application's context.
|
||||
*
|
||||
|
@ -170,42 +187,44 @@ final class Utilities {
|
|||
* thumbnail could not be created.
|
||||
*/
|
||||
static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context) {
|
||||
if (sIconWidth == -1) {
|
||||
final Resources resources = context.getResources();
|
||||
sIconWidth = sIconHeight = (int) resources.getDimension(
|
||||
android.R.dimen.app_icon_size);
|
||||
}
|
||||
|
||||
int width = sIconWidth;
|
||||
int height = sIconHeight;
|
||||
|
||||
final int bitmapWidth = bitmap.getWidth();
|
||||
final int bitmapHeight = bitmap.getHeight();
|
||||
|
||||
if (width > 0 && height > 0 && (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);
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
final Resources resources = context.getResources();
|
||||
sIconWidth = sIconHeight = (int) resources.getDimension(
|
||||
android.R.dimen.app_icon_size);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
int width = sIconWidth;
|
||||
int height = sIconHeight;
|
||||
|
||||
return bitmap;
|
||||
final int bitmapWidth = bitmap.getWidth();
|
||||
final int bitmapHeight = bitmap.getHeight();
|
||||
|
||||
if (width > 0 && height > 0 && (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;
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
static class BubbleText {
|
||||
|
@ -261,7 +280,6 @@ final class Utilities {
|
|||
mFirstLineY = (int)(leading + ascent + 0.5f);
|
||||
mLineHeight = (int)(leading + ascent + descent + 0.5f);
|
||||
|
||||
roundToPow2(64);
|
||||
mBitmapWidth = roundToPow2((int)(mBubbleRect.width() + 0.5f));
|
||||
mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Rect;
|
||||
|
@ -100,7 +101,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
private int[] mTempEstimate = new int[2];
|
||||
|
||||
private boolean mAllowLongPress;
|
||||
private boolean mLocked;
|
||||
|
||||
private int mTouchSlop;
|
||||
private int mMaximumVelocity;
|
||||
|
@ -642,10 +642,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
Log.d(Launcher.LOG_TAG, "Workspace onIntercept " + ev + " mLocked=" + mLocked
|
||||
+ " mLauncher.isDrawerDown()=" + mLauncher.isDrawerDown());
|
||||
if (mLocked || !mLauncher.isDrawerDown()) {
|
||||
Log.d(Launcher.LOG_TAG, "returning false");
|
||||
if (mLauncher.isWorkspaceLocked() || !mLauncher.isDrawerDown()) {
|
||||
return false; // We don't want the events. Let them fall through to the all apps view.
|
||||
}
|
||||
|
||||
|
@ -755,9 +752,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
|
||||
Log.d(Launcher.LOG_TAG, "Workspace onTouchEvent " + ev);
|
||||
|
||||
if (mLocked || !mLauncher.isDrawerDown()) {
|
||||
if (mLauncher.isWorkspaceLocked() || !mLauncher.isDrawerDown()) {
|
||||
return false; // We don't want the events. Let them fall through to the all apps view.
|
||||
}
|
||||
|
||||
|
@ -990,8 +985,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
cellLayout.onDropChild(view, mTargetCell);
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
|
||||
|
||||
final LauncherModel model = Launcher.getModel();
|
||||
model.addDesktopItem(info);
|
||||
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
|
||||
}
|
||||
|
@ -1088,7 +1081,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
|
||||
}
|
||||
final Object tag = mDragInfo.cell.getTag();
|
||||
Launcher.getModel().removeDesktopItem((ItemInfo) tag);
|
||||
}
|
||||
} else {
|
||||
if (mDragInfo != null) {
|
||||
|
@ -1186,24 +1178,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the SlidingDrawer so that touch events are processed.
|
||||
*
|
||||
* @see #lock()
|
||||
*/
|
||||
public void unlock() {
|
||||
mLocked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the SlidingDrawer so that touch events are ignores.
|
||||
*
|
||||
* @see #unlock()
|
||||
*/
|
||||
public void lock() {
|
||||
mLocked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True is long presses are still allowed for the current touch
|
||||
*/
|
||||
|
@ -1221,7 +1195,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
|
||||
void removeShortcutsForPackage(String packageName) {
|
||||
final ArrayList<View> childrenToRemove = new ArrayList<View>();
|
||||
final LauncherModel model = Launcher.getModel();
|
||||
final int count = getChildCount();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
@ -1244,7 +1217,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
|
||||
if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
|
||||
name != null && packageName.equals(name.getPackageName())) {
|
||||
model.removeDesktopItem(info);
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, info);
|
||||
childrenToRemove.add(view);
|
||||
}
|
||||
|
@ -1293,6 +1265,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
}
|
||||
|
||||
void updateShortcutsForPackage(String packageName) {
|
||||
final PackageManager pm = mLauncher.getPackageManager();
|
||||
|
||||
final int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CellLayout layout = (CellLayout) getChildAt(i);
|
||||
|
@ -1311,11 +1285,10 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
|||
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null &&
|
||||
packageName.equals(name.getPackageName())) {
|
||||
|
||||
final Drawable icon = Launcher.getModel().getApplicationInfoIcon(
|
||||
mLauncher.getPackageManager(), info);
|
||||
final Drawable icon = AppInfoCache.getIconDrawable(pm, info);
|
||||
if (icon != null && icon != info.icon) {
|
||||
info.icon.setCallback(null);
|
||||
info.icon = Utilities.createIconThumbnail(icon, mContext);
|
||||
info.icon = Utilities.createIconThumbnail(icon, mContext, false);
|
||||
info.filtered = true;
|
||||
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
|
||||
info.icon, null, null);
|
||||
|
|
Loading…
Reference in New Issue