DO NOT MERGE - Use the froyo launcher2 in mr3, except for a few unbundling things that can't be merged back.
This commit is contained in:
+1
-1
@@ -17,7 +17,7 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
#LOCAL_MODULE_TAGS := user
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-subdir-java-files)
|
||||
|
||||
|
||||
+3
-1
@@ -21,7 +21,9 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.launcher2"
|
||||
>
|
||||
|
||||
|
||||
<original-package android:name="com.android.launcher2" />
|
||||
|
||||
<permission
|
||||
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
|
||||
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<com.android.launcher2.HandleView
|
||||
android:id="@+id/all_apps_button"
|
||||
android:layout_width="@dimen/button_bar_height"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
|
||||
android:focusable="true"
|
||||
@@ -95,8 +95,9 @@
|
||||
|
||||
<com.android.launcher2.DeleteZone
|
||||
android:id="@+id/delete_zone"
|
||||
android:layout_width="49dip"
|
||||
android:layout_width="@dimen/button_bar_height"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/delete_zone_selector"
|
||||
|
||||
@@ -20,11 +20,12 @@
|
||||
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:hapticFeedbackEnabled="false"
|
||||
|
||||
launcher:cellWidth="@dimen/workspace_cell_width"
|
||||
launcher:cellHeight="@dimen/workspace_cell_height"
|
||||
launcher:longAxisStartPadding="0dip"
|
||||
launcher:longAxisEndPadding="55dip"
|
||||
launcher:longAxisStartPadding="65dip"
|
||||
launcher:longAxisEndPadding="65dip"
|
||||
launcher:shortAxisStartPadding="0dip"
|
||||
launcher:shortAxisEndPadding="0dip"
|
||||
launcher:shortAxisCells="4"
|
||||
|
||||
@@ -20,11 +20,12 @@
|
||||
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:hapticFeedbackEnabled="false"
|
||||
|
||||
launcher:cellWidth="@dimen/workspace_cell_width"
|
||||
launcher:cellHeight="@dimen/workspace_cell_height"
|
||||
launcher:longAxisStartPadding="0dip"
|
||||
launcher:longAxisEndPadding="55dip"
|
||||
launcher:longAxisStartPadding="8dip"
|
||||
launcher:longAxisEndPadding="@dimen/button_bar_height"
|
||||
launcher:shortAxisStartPadding="0dip"
|
||||
launcher:shortAxisEndPadding="0dip"
|
||||
launcher:shortAxisCells="4"
|
||||
|
||||
@@ -20,6 +20,7 @@ float g_DT;
|
||||
int g_LastTime;
|
||||
int g_PosMax;
|
||||
float g_Zoom;
|
||||
float g_Animation;
|
||||
float g_OldPosPage;
|
||||
float g_OldPosVelocity;
|
||||
float g_OldZoom;
|
||||
@@ -250,50 +251,27 @@ void updatePos() {
|
||||
g_PosPage = clampf(g_PosPage, -0.49, g_PosMax + 0.49);
|
||||
}
|
||||
|
||||
int positionStrip(float row, float column, int isTop, float p, int isText)
|
||||
{
|
||||
float mat1[16];
|
||||
float x = 0.5f * (column - 1.5f);
|
||||
float scale = 72.f * 3 / getWidth();
|
||||
|
||||
if (isTop) {
|
||||
matrixLoadTranslate(mat1, x, 0.8f, 0.f);
|
||||
matrixScale(mat1, scale, scale, 1.f);
|
||||
} else {
|
||||
matrixLoadTranslate(mat1, x, -0.9f, 0.f);
|
||||
matrixScale(mat1, scale, -scale, 1.f);
|
||||
}
|
||||
matrixTranslate(mat1, 0, p * 2, 0.f);
|
||||
matrixRotate(mat1, -p * 50, 1, 0, 0);
|
||||
vpLoadModelMatrix(mat1);
|
||||
|
||||
float soff = -(row * 1.4);
|
||||
if (isTop) {
|
||||
matrixLoadScale(mat1, 1.f, -0.85f, 1.f);
|
||||
if (isText) {
|
||||
matrixScale(mat1, 1.f, 2.f, 1.f);
|
||||
}
|
||||
matrixTranslate(mat1, 0, soff - 0.95f + 0.18f, 0);
|
||||
} else {
|
||||
matrixLoadScale(mat1, 1.f, 0.85f, 1.f);
|
||||
if (isText) {
|
||||
matrixScale(mat1, 1.f, 2.f, 1.f);
|
||||
}
|
||||
matrixTranslate(mat1, 0, soff - 0.65f, 0);
|
||||
}
|
||||
vpLoadTextureMatrix(mat1);
|
||||
return -(soff + 0.3f) * 10.f;
|
||||
}
|
||||
|
||||
void
|
||||
draw_home_button()
|
||||
{
|
||||
setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
bindTexture(NAMED_PFTexNearest, 0, state->homeButtonId);
|
||||
float x = (SCREEN_WIDTH_PX - params->homeButtonTextureWidth) / 2;
|
||||
float y = (g_Zoom - 1.f) * params->homeButtonTextureHeight;
|
||||
|
||||
y -= 30; // move the house to the edge of the screen as it doesn't fill the texture.
|
||||
float w = getWidth();
|
||||
float h = getHeight();
|
||||
|
||||
float x;
|
||||
float y;
|
||||
if (getWidth() > getHeight()) {
|
||||
x = w - (params->homeButtonTextureWidth * (1 - g_Animation)) + 20;
|
||||
y = (h - params->homeButtonTextureHeight) * 0.5f;
|
||||
} else {
|
||||
x = (w - params->homeButtonTextureWidth) / 2;
|
||||
y = -g_Animation * params->homeButtonTextureHeight;
|
||||
y -= 30; // move the house to the edge of the screen as it doesn't fill the texture.
|
||||
}
|
||||
|
||||
drawSpriteScreenspace(x, y, 0, params->homeButtonTextureWidth, params->homeButtonTextureHeight);
|
||||
}
|
||||
|
||||
@@ -304,124 +282,66 @@ void drawFrontGrid(float rowOffset, float p)
|
||||
|
||||
int intRowOffset = rowOffset;
|
||||
float rowFrac = rowOffset - intRowOffset;
|
||||
float colWidth = getWidth() / 4;
|
||||
float colWidth = 120.f;//getWidth() / 4;
|
||||
float rowHeight = colWidth + 25.f;
|
||||
float yoff = h - ((h - (rowHeight * 4.f)) / 2);
|
||||
|
||||
yoff -= 110;
|
||||
float yoff = 0.5f * h + 1.5f * rowHeight;
|
||||
|
||||
int row, col;
|
||||
int iconNum = intRowOffset * 4;
|
||||
float ymax = yoff + rowHeight;
|
||||
float ymin = yoff - (3 * rowHeight) - 70;
|
||||
float gridTop = yoff -3;
|
||||
float gridBottom = ymin;
|
||||
int colCount = 4;
|
||||
if (w > h) {
|
||||
colCount = 6;
|
||||
rowHeight -= 12.f;
|
||||
yoff = 0.47f * h + 1.0f * rowHeight;
|
||||
}
|
||||
|
||||
gridBottom += 50;
|
||||
int iconNum = (intRowOffset - 5) * colCount;
|
||||
|
||||
for (row = 0; row < 5; row++) {
|
||||
|
||||
bindProgramVertex(NAMED_PVCurve);
|
||||
|
||||
vpConstants->Position.z = p;
|
||||
|
||||
setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
for (row = -5; row < 15; row++) {
|
||||
float y = yoff - ((-rowFrac + row) * rowHeight);
|
||||
|
||||
for (col=0; col < 4; col++) {
|
||||
for (col=0; col < colCount; col++) {
|
||||
if (iconNum >= state->iconCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iconNum >= 0) {
|
||||
float x = colWidth * col - ((128 - colWidth) / 2);
|
||||
float x = colWidth * col + (colWidth / 2);
|
||||
vpConstants->Position.x = x;
|
||||
|
||||
if ((y >= ymin) && (y <= ymax)) {
|
||||
float iconY = y - 20;
|
||||
setColor(1.f, 1.f, 1.f, 1.f);
|
||||
if (state->selectedIconIndex == iconNum && !p) {
|
||||
bindTexture(NAMED_PFTexNearest, 0, state->selectedIconTexture);
|
||||
drawSpriteScreenspace(x, iconY, 0, 128, 128);
|
||||
}
|
||||
|
||||
bindTexture(NAMED_PFTexNearest, 0, loadI32(ALLOC_ICON_IDS, iconNum));
|
||||
if (!p) {
|
||||
int cropT = 0;
|
||||
if (y > gridTop) {
|
||||
cropT = y - gridTop;
|
||||
}
|
||||
int cropB = 0;
|
||||
if (y < gridBottom) {
|
||||
cropB = gridBottom - y;
|
||||
}
|
||||
drawSpriteScreenspaceCropped(x, iconY+cropB, 0, 128, 128-cropT-cropB,
|
||||
0, 128-cropB, 128, -128+cropT+cropB);
|
||||
} else {
|
||||
float px = ((x + 64) - (getWidth() / 2)) / (getWidth() / 2);
|
||||
float py = ((iconY + 64) - (getHeight() / 2)) / (getWidth() / 2);
|
||||
float d = 64.f / (getWidth() / 2);
|
||||
px *= p + 1;
|
||||
py *= p + 1;
|
||||
drawQuadTexCoords(px - d, py - d, -p, 0, 1,
|
||||
px - d, py + d, -p, 0, 0,
|
||||
px + d, py + d, -p, 1, 0,
|
||||
px + d, py - d, -p, 1, 1);
|
||||
}
|
||||
if (state->selectedIconIndex == iconNum && !p) {
|
||||
bindProgramFragment(NAMED_PFTexNearest);
|
||||
bindTexture(NAMED_PFTexNearest, 0, state->selectedIconTexture);
|
||||
vpConstants->ImgSize.x = SELECTION_TEXTURE_WIDTH_PX;
|
||||
vpConstants->ImgSize.y = SELECTION_TEXTURE_HEIGHT_PX;
|
||||
vpConstants->Position.y = y - (SELECTION_TEXTURE_HEIGHT_PX - ICON_TEXTURE_HEIGHT_PX) * 0.5f;
|
||||
drawSimpleMesh(NAMED_SMCell);
|
||||
}
|
||||
|
||||
bindProgramFragment(NAMED_PFTexMip);
|
||||
vpConstants->ImgSize.x = ICON_TEXTURE_WIDTH_PX;
|
||||
vpConstants->ImgSize.y = ICON_TEXTURE_HEIGHT_PX;
|
||||
vpConstants->Position.y = y;
|
||||
bindTexture(NAMED_PFTexMip, 0, loadI32(ALLOC_ICON_IDS, iconNum));
|
||||
drawSimpleMesh(NAMED_SMCell);
|
||||
|
||||
bindProgramFragment(NAMED_PFTexMipAlpha);
|
||||
vpConstants->ImgSize.x = 120.f;
|
||||
vpConstants->ImgSize.y = 64.f;
|
||||
vpConstants->Position.y = y - 64.f;
|
||||
bindTexture(NAMED_PFTexMipAlpha, 0, loadI32(ALLOC_LABEL_IDS, iconNum));
|
||||
drawSimpleMesh(NAMED_SMCell);
|
||||
}
|
||||
iconNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawStrip(float row, float column, int isTop, int iconNum, float p)
|
||||
{
|
||||
if (iconNum < 0) return;
|
||||
int offset = positionStrip(row, column, isTop, p, 0);
|
||||
bindTexture(NAMED_PFTexMip, 0, loadI32(ALLOC_ICON_IDS, iconNum));
|
||||
if (offset < -20) return;
|
||||
offset = clamp(offset, 0, 199 - 20);
|
||||
|
||||
int len = 20;
|
||||
if (isTop && (offset < 7)) {
|
||||
len -= 7 - offset;
|
||||
offset = 7;
|
||||
}
|
||||
|
||||
drawSimpleMeshRange(NAMED_SMMesh, offset * 6, len * 6);
|
||||
//drawSimpleMesh(NAMED_SMMesh);
|
||||
}
|
||||
|
||||
void drawTop(float rowOffset, float p)
|
||||
{
|
||||
int row, col;
|
||||
int iconNum = 0;
|
||||
for (row = 0; row <= (int)(rowOffset+1); row++) {
|
||||
for (col=0; col < 4; col++) {
|
||||
if (iconNum >= state->iconCount) {
|
||||
return;
|
||||
}
|
||||
drawStrip(rowOffset - row, col, 1, iconNum, p);
|
||||
iconNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawBottom(float rowOffset, float p)
|
||||
{
|
||||
float pos = -1.f;
|
||||
int intRowOffset = rowOffset;
|
||||
pos -= rowOffset - intRowOffset;
|
||||
|
||||
int row, col;
|
||||
int iconNum = (intRowOffset + 3) * 4;
|
||||
while (1) {
|
||||
for (col=0; col < 4; col++) {
|
||||
if (iconNum >= state->iconCount) {
|
||||
return;
|
||||
}
|
||||
if (pos > -1) {
|
||||
drawStrip(pos, col, 0, iconNum, p);
|
||||
}
|
||||
iconNum++;
|
||||
}
|
||||
pos += 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int launchID)
|
||||
@@ -440,24 +360,16 @@ main(int launchID)
|
||||
g_DT = minf(g_DT, 0.2f);
|
||||
|
||||
if (g_Zoom != state->zoomTarget) {
|
||||
float dz;
|
||||
if (state->zoomTarget > 0.5f) {
|
||||
dz = (1 - g_Zoom) * 0.2f;
|
||||
} else {
|
||||
dz = -g_DT - (1 - g_Zoom) * 0.2f;
|
||||
}
|
||||
if (dz && (fabsf(dz) < 0.02f)) {
|
||||
if (dz > 0) {
|
||||
dz = 0.02f;
|
||||
} else {
|
||||
dz = -0.02f;
|
||||
}
|
||||
float dz = g_DT * 1.7f;
|
||||
if (state->zoomTarget < 0.5f) {
|
||||
dz = -dz;
|
||||
}
|
||||
if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) {
|
||||
g_Zoom = state->zoomTarget;
|
||||
} else {
|
||||
g_Zoom += dz;
|
||||
}
|
||||
g_Animation = powf(1-g_Zoom, 3);
|
||||
updateReadback();
|
||||
}
|
||||
|
||||
@@ -484,31 +396,11 @@ main(int launchID)
|
||||
//debugF(" draw g_PosPage", g_PosPage);
|
||||
|
||||
// Draw the icons ========================================
|
||||
|
||||
/*
|
||||
bindProgramFragment(NAMED_PFColor);
|
||||
positionStrip(1, 0, 1, 0, 0);
|
||||
drawSimpleMesh(NAMED_SMMesh);
|
||||
*/
|
||||
|
||||
bindProgramFragment(NAMED_PFTexMip);
|
||||
|
||||
drawTop(g_PosPage, 1-g_Zoom);
|
||||
drawBottom(g_PosPage, 1-g_Zoom);
|
||||
|
||||
bindProgramFragment(NAMED_PFTexMip);
|
||||
{
|
||||
float mat1[16];
|
||||
matrixLoadIdentity(mat1);
|
||||
vpLoadModelMatrix(mat1);
|
||||
vpLoadTextureMatrix(mat1);
|
||||
}
|
||||
drawFrontGrid(g_PosPage, g_Animation);
|
||||
|
||||
bindProgramFragment(NAMED_PFTexNearest);
|
||||
drawFrontGrid(g_PosPage, 1-g_Zoom);
|
||||
draw_home_button();
|
||||
|
||||
|
||||
// This is a WAR to do a rendering pass without drawing during init to
|
||||
// force the driver to preload and compile its shaders.
|
||||
// Without this the first animation does not appear due to the time it
|
||||
-432
@@ -1,432 +0,0 @@
|
||||
#pragma version(1)
|
||||
#pragma stateVertex(PV)
|
||||
#pragma stateFragment(PFTexLinear)
|
||||
#pragma stateStore(PSIcons)
|
||||
|
||||
#define PI 3.14159f
|
||||
|
||||
|
||||
// Attraction to center values from page edge to page center.
|
||||
float g_AttractionTable[9];
|
||||
float g_FrictionTable[9];
|
||||
float g_PhysicsTableSize;
|
||||
|
||||
float g_PosPage;
|
||||
float g_PosVelocity;
|
||||
float g_LastPositionX;
|
||||
int g_LastTouchDown;
|
||||
float g_DT;
|
||||
int g_LastTime;
|
||||
int g_PageCount;
|
||||
float g_Zoom;
|
||||
|
||||
// Drawing constants, should be parameters ======
|
||||
#define VIEW_ANGLE 1.28700222f
|
||||
|
||||
float g_OldPosPage;
|
||||
float g_OldPosVelocity;
|
||||
float g_OldZoom;
|
||||
|
||||
int g_DrawLastFrame;
|
||||
int lastFrame(int draw) {
|
||||
// We draw one extra frame to work around the last frame post bug.
|
||||
// We also need to track if we drew the last frame to deal with large DT
|
||||
// in the physics.
|
||||
int ret = g_DrawLastFrame | draw;
|
||||
g_DrawLastFrame = draw;
|
||||
return ret; // should return draw instead.
|
||||
}
|
||||
|
||||
void updateReadback() {
|
||||
if ((g_OldPosPage != g_PosPage) ||
|
||||
(g_OldPosVelocity != g_PosVelocity) ||
|
||||
(g_OldZoom != g_Zoom)) {
|
||||
|
||||
g_OldPosPage = g_PosPage;
|
||||
g_OldPosVelocity = g_PosVelocity;
|
||||
g_OldZoom = g_Zoom;
|
||||
|
||||
int i[3];
|
||||
i[0] = g_PosPage * (1 << 16);
|
||||
i[1] = g_PosVelocity * (1 << 16);
|
||||
i[2] = g_OldZoom * (1 << 16);
|
||||
sendToClient(&i[0], 1, 12, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
g_AttractionTable[0] = 6.5f;
|
||||
g_AttractionTable[1] = 6.5f;
|
||||
g_AttractionTable[2] = 7.0f;
|
||||
g_AttractionTable[3] = 6.0f;
|
||||
g_AttractionTable[4] = -6.0f;
|
||||
g_AttractionTable[5] = -7.0f;
|
||||
g_AttractionTable[6] = -6.5f;
|
||||
g_AttractionTable[7] = -6.5f;
|
||||
g_AttractionTable[8] = -6.5f; // dup 7 to avoid a clamp later
|
||||
g_FrictionTable[0] = 3.5f;
|
||||
g_FrictionTable[1] = 3.6f;
|
||||
g_FrictionTable[2] = 4.0f;
|
||||
g_FrictionTable[3] = 5.0f;
|
||||
g_FrictionTable[4] = 5.0f;
|
||||
g_FrictionTable[5] = 4.0f;
|
||||
g_FrictionTable[6] = 3.6f;
|
||||
g_FrictionTable[7] = 3.5f;
|
||||
g_FrictionTable[8] = 3.5f; // dup 7 to avoid a clamp later
|
||||
g_PhysicsTableSize = 7;
|
||||
|
||||
g_PosVelocity = 0;
|
||||
g_PosPage = 0;
|
||||
g_LastTouchDown = 0;
|
||||
g_LastPositionX = 0;
|
||||
g_Zoom = 0;
|
||||
}
|
||||
|
||||
void resetHWWar() {
|
||||
}
|
||||
|
||||
void move() {
|
||||
if (g_LastTouchDown) {
|
||||
float dx = -(state->newPositionX - g_LastPositionX);
|
||||
g_PosVelocity = 0;
|
||||
g_PosPage += dx;
|
||||
|
||||
float pmin = -0.25f;
|
||||
float pmax = (g_PageCount - 1) + 0.25f;
|
||||
g_PosPage = clampf(g_PosPage, pmin, pmax);
|
||||
}
|
||||
g_LastTouchDown = state->newTouchDown;
|
||||
g_LastPositionX = state->newPositionX;
|
||||
//debugF("Move P", g_PosPage);
|
||||
}
|
||||
|
||||
void fling() {
|
||||
g_LastTouchDown = 0;
|
||||
g_PosVelocity = -state->flingVelocityX;
|
||||
float av = fabsf(g_PosVelocity);
|
||||
float minVel = 3.5f;
|
||||
|
||||
minVel *= 1.f - (fabsf(fracf(g_PosPage + 0.5f) - 0.5f) * 0.45f);
|
||||
|
||||
if (av < minVel && av > 0.2f) {
|
||||
if (g_PosVelocity > 0) {
|
||||
g_PosVelocity = minVel;
|
||||
} else {
|
||||
g_PosVelocity = -minVel;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_PosPage <= 0) {
|
||||
g_PosVelocity = maxf(0, g_PosVelocity);
|
||||
}
|
||||
if (g_PosPage > (g_PageCount - 1)) {
|
||||
g_PosVelocity = minf(0, g_PosVelocity);
|
||||
}
|
||||
//debugF("fling v", g_PosVelocity);
|
||||
}
|
||||
|
||||
void touchUp() {
|
||||
g_LastTouchDown = 0;
|
||||
}
|
||||
|
||||
int
|
||||
count_pages(int iconCount)
|
||||
{
|
||||
int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
|
||||
int pages = iconCount / iconsPerPage;
|
||||
if (pages*iconsPerPage != iconCount) {
|
||||
pages++;
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
float
|
||||
modf(float x, float y)
|
||||
{
|
||||
return x-(y*floorf(x/y));
|
||||
}
|
||||
|
||||
void updatePos() {
|
||||
if (g_LastTouchDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
float tablePosNorm = fracf(g_PosPage + 0.5f);
|
||||
float tablePosF = tablePosNorm * g_PhysicsTableSize;
|
||||
int tablePosI = tablePosF;
|
||||
float tablePosFrac = tablePosF - tablePosI;
|
||||
float accel = lerpf(g_AttractionTable[tablePosI],
|
||||
g_AttractionTable[tablePosI + 1],
|
||||
tablePosFrac) * g_DT;
|
||||
float friction = lerpf(g_FrictionTable[tablePosI],
|
||||
g_FrictionTable[tablePosI + 1],
|
||||
tablePosFrac) * g_DT;
|
||||
//debugF(" accel", accel);
|
||||
//debugF(" friction", friction);
|
||||
|
||||
// If our velocity is low OR acceleration is opposing it, apply it.
|
||||
if (fabsf(g_PosVelocity) < 1.0f || (g_PosVelocity * accel) < 0) {
|
||||
g_PosVelocity += accel;
|
||||
}
|
||||
|
||||
if ((friction > fabsf(g_PosVelocity)) && (friction > fabsf(accel))) {
|
||||
// Special get back to center and overcome friction physics.
|
||||
float t = tablePosNorm - 0.5f;
|
||||
if (fabsf(t) < (friction * g_DT)) {
|
||||
// really close, just snap
|
||||
g_PosPage = roundf(g_PosPage);
|
||||
g_PosVelocity = 0;
|
||||
} else {
|
||||
if (t > 0) {
|
||||
g_PosVelocity = -friction;
|
||||
} else {
|
||||
g_PosVelocity = friction;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal physics
|
||||
if (g_PosVelocity > 0) {
|
||||
g_PosVelocity -= friction;
|
||||
g_PosVelocity = maxf(g_PosVelocity, 0);
|
||||
} else {
|
||||
g_PosVelocity += friction;
|
||||
g_PosVelocity = minf(g_PosVelocity, 0);
|
||||
}
|
||||
}
|
||||
g_PosPage += g_PosVelocity * g_DT;
|
||||
|
||||
// Check for out of boundry conditions.
|
||||
if (g_PosPage < 0 && g_PosVelocity < 0) {
|
||||
float damp = 1.0 + (g_PosPage * 4);
|
||||
damp = clampf(damp, 0.f, 0.9f);
|
||||
g_PosVelocity *= damp;
|
||||
}
|
||||
if (g_PosPage > (g_PageCount-1) && g_PosVelocity > 0) {
|
||||
float damp = 1.0 - ((g_PosPage - g_PageCount + 1) * 4);
|
||||
damp = clampf(damp, 0.f, 0.9f);
|
||||
g_PosVelocity *= damp;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
far_size(float sizeAt0)
|
||||
{
|
||||
return sizeAt0 * (RADIUS+2) / 2; // -2 is the camera z=(z-camZ)/z
|
||||
}
|
||||
|
||||
void
|
||||
draw_page(int icon, int lastIcon, float centerAngle, float scale)
|
||||
{
|
||||
int row;
|
||||
int col;
|
||||
|
||||
//debugF("center angle", centerAngle);
|
||||
|
||||
float iconTextureWidth = ICON_WIDTH_PX / (float)ICON_TEXTURE_WIDTH_PX;
|
||||
float iconTextureHeight = ICON_HEIGHT_PX / (float)ICON_TEXTURE_HEIGHT_PX;
|
||||
|
||||
float iconWidthAngle = VIEW_ANGLE * ICON_WIDTH_PX / SCREEN_WIDTH_PX;
|
||||
float columnGutterAngle = iconWidthAngle * 0.9f;
|
||||
|
||||
float farIconSize = FAR_ICON_SIZE;
|
||||
float iconGutterHeight = farIconSize * 1.3f;
|
||||
|
||||
float farIconTextureSize = far_size(2 * ICON_TEXTURE_WIDTH_PX / (float)SCREEN_WIDTH_PX);
|
||||
|
||||
float normalizedLabelWidth = 2 * params->bubbleWidth / (float)SCREEN_WIDTH_PX;
|
||||
float farLabelHeight = far_size(params->bubbleHeight * (normalizedLabelWidth / params->bubbleWidth));
|
||||
|
||||
for (row=0; row<ROWS_PER_PAGE && icon<=lastIcon; row++) {
|
||||
float angle = centerAngle;
|
||||
angle -= (columnGutterAngle + iconWidthAngle) * 1.5f;
|
||||
|
||||
float iconTop = (farIconSize + iconGutterHeight) * (1.85f + ICON_TOP_OFFSET)
|
||||
- row * (farIconSize + iconGutterHeight);
|
||||
float iconBottom = iconTop - farIconSize;
|
||||
|
||||
float labelY = iconBottom - farLabelHeight;
|
||||
float iconTextureTop = iconTop + (0.5f * (farIconTextureSize - farIconSize));
|
||||
float iconTextureBottom = iconTextureTop - farIconTextureSize;
|
||||
|
||||
for (col=0; col<COLUMNS_PER_PAGE && icon<=lastIcon; col++) {
|
||||
// icon
|
||||
float sine = sinf(angle);
|
||||
float cosine = cosf(angle);
|
||||
|
||||
float centerX = sine * RADIUS;
|
||||
float centerZ = cosine * RADIUS / scale;
|
||||
|
||||
if (scale > 1.f) {
|
||||
centerX *= scale;
|
||||
}
|
||||
|
||||
float iconLeftX = centerX - (/*cosine * */ farIconTextureSize * .5);
|
||||
float iconRightX = centerX + (/*cosine * */ farIconTextureSize * .5);
|
||||
float iconLeftZ = centerZ;// + (sine * farIconTextureSize * .5);
|
||||
float iconRightZ = centerZ;// - (sine * farIconTextureSize * .5);
|
||||
|
||||
color(1.0f, 1.0f, 1.0f, 0.99f);
|
||||
if (state->selectedIconIndex == icon) {
|
||||
bindTexture(NAMED_PFTexLinear, 0, state->selectedIconTexture);
|
||||
drawQuadTexCoords(
|
||||
iconLeftX, iconTextureTop, iconLeftZ, 0.0f, 0.0f,
|
||||
iconRightX, iconTextureTop, iconRightZ, 1.0f, 0.0f,
|
||||
iconRightX, iconTextureBottom, iconRightZ, 1.0f, 1.0f,
|
||||
iconLeftX, iconTextureBottom, iconLeftZ, 0.0f, 1.0f);
|
||||
} else {
|
||||
bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, icon));
|
||||
drawQuadTexCoords(
|
||||
iconLeftX, iconTextureTop, iconLeftZ, 0.0f, 0.0f,
|
||||
iconRightX, iconTextureTop, iconRightZ, 1.0f, 0.0f,
|
||||
iconRightX, iconTextureBottom, iconRightZ, 1.0f, 1.0f,
|
||||
iconLeftX, iconTextureBottom, iconLeftZ, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
// label
|
||||
if (scale < 1.2f) {
|
||||
float a = (1.2f - maxf(scale, 1.0f)) * 5;
|
||||
color(1.0f, 1.0f, 1.0f, a);
|
||||
bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_LABEL_IDS, icon));
|
||||
drawSprite(centerX, labelY, centerZ,
|
||||
params->bubbleBitmapWidth, params->bubbleBitmapHeight);
|
||||
}
|
||||
|
||||
angle += columnGutterAngle + iconWidthAngle;
|
||||
icon++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_home_button()
|
||||
{
|
||||
color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
bindTexture(NAMED_PFTexLinear, 0, state->homeButtonId);
|
||||
|
||||
float scale = 2.0f / SCREEN_WIDTH_PX;
|
||||
|
||||
float x = 0.0f;
|
||||
|
||||
float y = -(SCREEN_HEIGHT_PX / (float)SCREEN_WIDTH_PX);
|
||||
y += g_Zoom * (scale * params->homeButtonTextureHeight / 2);
|
||||
|
||||
float z = 0.0f;
|
||||
drawSprite(x, y, z, params->homeButtonTextureWidth, params->homeButtonTextureHeight);
|
||||
}
|
||||
|
||||
int
|
||||
main(int launchID)
|
||||
{
|
||||
// Compute dt in seconds.
|
||||
int newTime = uptimeMillis();
|
||||
g_DT = (newTime - g_LastTime) / 1000.f;
|
||||
g_LastTime = newTime;
|
||||
|
||||
if (!g_DrawLastFrame) {
|
||||
// If we stopped rendering we cannot use DT.
|
||||
// assume 30fps in this case.
|
||||
g_DT = 0.033f;
|
||||
}
|
||||
if (g_DT > 0.2f) {
|
||||
// physics may break if DT is large.
|
||||
g_DT = 0.2f;
|
||||
}
|
||||
|
||||
//debugF("zoom", g_Zoom);
|
||||
if (g_Zoom != state->zoomTarget) {
|
||||
float dz = (state->zoomTarget - g_Zoom) * g_DT * 5;
|
||||
if (dz && (fabsf(dz) < 0.03f)) {
|
||||
if (dz > 0) {
|
||||
dz = 0.03f;
|
||||
} else {
|
||||
dz = -0.03f;
|
||||
}
|
||||
}
|
||||
if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) {
|
||||
g_Zoom = state->zoomTarget;
|
||||
} else {
|
||||
g_Zoom += dz;
|
||||
}
|
||||
updateReadback();
|
||||
}
|
||||
|
||||
// Set clear value to dim the background based on the zoom position.
|
||||
if ((g_Zoom < 0.001f) && (state->zoomTarget < 0.001f)) {
|
||||
pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
// When we're zoomed out and not tracking motion events, reset the pos to 0.
|
||||
if (!g_LastTouchDown) {
|
||||
g_PosPage = 0;
|
||||
}
|
||||
return lastFrame(0);
|
||||
} else if (g_Zoom < 0.85f) {
|
||||
pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
|
||||
} else {
|
||||
pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
|
||||
}
|
||||
|
||||
// icons & labels
|
||||
int iconCount = state->iconCount;
|
||||
g_PageCount = count_pages(iconCount);
|
||||
|
||||
updatePos(0.1f);
|
||||
updateReadback();
|
||||
|
||||
//debugF(" draw g_PosPage", g_PosPage);
|
||||
|
||||
// Draw the icons ========================================
|
||||
|
||||
// Bug makes 1.0f alpha fail.
|
||||
color(1.0f, 1.0f, 1.0f, 0.99f);
|
||||
|
||||
if (iconCount <= 0) {
|
||||
return lastFrame(0);
|
||||
}
|
||||
int lastIcon = iconCount-1;
|
||||
|
||||
int page = g_PosPage;
|
||||
float currentPagePosition = g_PosPage - page;
|
||||
|
||||
int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
|
||||
int icon = clamp(iconsPerPage * page, 0, lastIcon);
|
||||
|
||||
float scale = (1 / g_Zoom);
|
||||
|
||||
float pageAngle = VIEW_ANGLE * 1.2f;
|
||||
draw_page(icon, lastIcon, -pageAngle*currentPagePosition, scale);
|
||||
draw_page(icon+iconsPerPage, lastIcon, (-pageAngle*currentPagePosition)+pageAngle, scale);
|
||||
|
||||
// Draw the border lines for debugging ========================================
|
||||
/*
|
||||
bindProgramVertex(NAMED_PVOrtho);
|
||||
bindProgramFragment(NAMED_PFOrtho);
|
||||
bindProgramFragmentStore(NAMED_PFSText);
|
||||
|
||||
color(1.0f, 1.0f, 0.0f, 0.99f);
|
||||
int i;
|
||||
for (i=0; i<ROWS_PER_PAGE+1; i++) {
|
||||
int y = loadI32(ALLOC_Y_BORDERS, i);
|
||||
drawRect(0, y, SCREEN_WIDTH_PX, y+1, 0.0f);
|
||||
}
|
||||
for (i=0; i<COLUMNS_PER_PAGE+1; i++) {
|
||||
int x = loadI32(ALLOC_X_BORDERS, i);
|
||||
drawRect(x, 0, x+1, SCREEN_HEIGHT_PX, 0.0f);
|
||||
}
|
||||
*/
|
||||
|
||||
// Draw the home button ========================================
|
||||
draw_home_button();
|
||||
|
||||
/*
|
||||
bindTexture(NAMED_PFOrtho, 0, loadI32(ALLOC_PARAMS, PARAM_SCROLL_HANDLE_ID));
|
||||
float handleLeft = 40 + (320 * (scrollXPx/(float)(maxScrollXPx)));
|
||||
float handleTop = 680;
|
||||
float handleWidth = loadI32(ALLOC_PARAMS, PARAM_SCROLL_HANDLE_TEX_WIDTH);
|
||||
float handleHeight = loadI32(ALLOC_PARAMS, PARAM_SCROLL_HANDLE_TEX_HEIGHT);
|
||||
drawRect(handleLeft, handleTop, handleLeft+handleWidth, handleTop+handleHeight, 0.0f);
|
||||
*/
|
||||
|
||||
// Bug workaround where the last frame is not always displayed
|
||||
// So we keep rendering until the bug is fixed.
|
||||
return lastFrame((g_PosVelocity != 0) || fracf(g_PosPage) || (g_Zoom != state->zoomTarget));
|
||||
}
|
||||
|
||||
@@ -1,404 +0,0 @@
|
||||
#pragma version(1)
|
||||
#pragma stateVertex(PV)
|
||||
#pragma stateFragment(PFTexLinear)
|
||||
#pragma stateStore(PSIcons)
|
||||
|
||||
#define PI 3.14159f
|
||||
|
||||
|
||||
// Attraction to center values from page edge to page center.
|
||||
float g_AttractionTable[9];
|
||||
float g_FrictionTable[9];
|
||||
float g_PhysicsTableSize;
|
||||
|
||||
float g_PosPage;
|
||||
float g_PosVelocity;
|
||||
float g_LastPositionX;
|
||||
int g_LastTouchDown;
|
||||
float g_DT;
|
||||
int g_LastTime;
|
||||
int g_PageCount;
|
||||
float g_Zoom;
|
||||
float g_OldPosPage;
|
||||
float g_OldPosVelocity;
|
||||
float g_OldZoom;
|
||||
|
||||
// Drawing constants, should be parameters ======
|
||||
#define VIEW_ANGLE 1.28700222f
|
||||
|
||||
int g_DrawLastFrame;
|
||||
int lastFrame(int draw) {
|
||||
// We draw one extra frame to work around the last frame post bug.
|
||||
// We also need to track if we drew the last frame to deal with large DT
|
||||
// in the physics.
|
||||
int ret = g_DrawLastFrame | draw;
|
||||
g_DrawLastFrame = draw;
|
||||
return ret; // should return draw instead.
|
||||
}
|
||||
|
||||
void updateReadback() {
|
||||
if ((g_OldPosPage != g_PosPage) ||
|
||||
(g_OldPosVelocity != g_PosVelocity) ||
|
||||
(g_OldZoom != g_Zoom)) {
|
||||
|
||||
g_OldPosPage = g_PosPage;
|
||||
g_OldPosVelocity = g_PosVelocity;
|
||||
g_OldZoom = g_Zoom;
|
||||
|
||||
int i[3];
|
||||
i[0] = g_PosPage * (1 << 16);
|
||||
i[1] = g_PosVelocity * (1 << 16);
|
||||
i[2] = g_OldZoom * (1 << 16);
|
||||
sendToClient(&i[0], 1, 12, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
g_AttractionTable[0] = 6.5f;
|
||||
g_AttractionTable[1] = 6.5f;
|
||||
g_AttractionTable[2] = 7.0f;
|
||||
g_AttractionTable[3] = 6.0f;
|
||||
g_AttractionTable[4] = -6.0f;
|
||||
g_AttractionTable[5] = -7.0f;
|
||||
g_AttractionTable[6] = -6.5f;
|
||||
g_AttractionTable[7] = -6.5f;
|
||||
g_AttractionTable[8] = -6.5f; // dup 7 to avoid a clamp later
|
||||
g_FrictionTable[0] = 3.5f;
|
||||
g_FrictionTable[1] = 3.6f;
|
||||
g_FrictionTable[2] = 4.0f;
|
||||
g_FrictionTable[3] = 5.0f;
|
||||
g_FrictionTable[4] = 5.0f;
|
||||
g_FrictionTable[5] = 4.0f;
|
||||
g_FrictionTable[6] = 3.6f;
|
||||
g_FrictionTable[7] = 3.5f;
|
||||
g_FrictionTable[8] = 3.5f; // dup 7 to avoid a clamp later
|
||||
g_PhysicsTableSize = 7;
|
||||
|
||||
g_PosVelocity = 0;
|
||||
g_PosPage = 0;
|
||||
g_LastTouchDown = 0;
|
||||
g_LastPositionX = 0;
|
||||
g_Zoom = 0;
|
||||
}
|
||||
|
||||
void resetHWWar() {
|
||||
}
|
||||
|
||||
void move() {
|
||||
if (g_LastTouchDown) {
|
||||
float dx = -(state->newPositionX - g_LastPositionX);
|
||||
g_PosVelocity = 0;
|
||||
g_PosPage += dx;
|
||||
|
||||
float pmin = -0.25f;
|
||||
float pmax = (g_PageCount - 1) + 0.25f;
|
||||
g_PosPage = clampf(g_PosPage, pmin, pmax);
|
||||
}
|
||||
g_LastTouchDown = state->newTouchDown;
|
||||
g_LastPositionX = state->newPositionX;
|
||||
//debugF("Move P", g_PosPage);
|
||||
}
|
||||
|
||||
void fling() {
|
||||
g_LastTouchDown = 0;
|
||||
g_PosVelocity = -state->flingVelocityX;
|
||||
float av = fabsf(g_PosVelocity);
|
||||
float minVel = 3.5f;
|
||||
|
||||
minVel *= 1.f - (fabsf(fracf(g_PosPage + 0.5f) - 0.5f) * 0.45f);
|
||||
|
||||
if (av < minVel && av > 0.2f) {
|
||||
if (g_PosVelocity > 0) {
|
||||
g_PosVelocity = minVel;
|
||||
} else {
|
||||
g_PosVelocity = -minVel;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_PosPage <= 0) {
|
||||
g_PosVelocity = maxf(0, g_PosVelocity);
|
||||
}
|
||||
if (g_PosPage > (g_PageCount - 1)) {
|
||||
g_PosVelocity = minf(0, g_PosVelocity);
|
||||
}
|
||||
//debugF("fling v", g_PosVelocity);
|
||||
}
|
||||
|
||||
void touchUp() {
|
||||
g_LastTouchDown = 0;
|
||||
}
|
||||
|
||||
int
|
||||
count_pages(int iconCount)
|
||||
{
|
||||
int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
|
||||
int pages = iconCount / iconsPerPage;
|
||||
if (pages*iconsPerPage != iconCount) {
|
||||
pages++;
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
float
|
||||
modf(float x, float y)
|
||||
{
|
||||
return x-(y*floorf(x/y));
|
||||
}
|
||||
|
||||
void updatePos() {
|
||||
if (g_LastTouchDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
float tablePosNorm = fracf(g_PosPage + 0.5f);
|
||||
float tablePosF = tablePosNorm * g_PhysicsTableSize;
|
||||
int tablePosI = tablePosF;
|
||||
float tablePosFrac = tablePosF - tablePosI;
|
||||
float accel = lerpf(g_AttractionTable[tablePosI],
|
||||
g_AttractionTable[tablePosI + 1],
|
||||
tablePosFrac) * g_DT;
|
||||
float friction = lerpf(g_FrictionTable[tablePosI],
|
||||
g_FrictionTable[tablePosI + 1],
|
||||
tablePosFrac) * g_DT;
|
||||
//debugF(" accel", accel);
|
||||
//debugF(" friction", friction);
|
||||
|
||||
// If our velocity is low OR acceleration is opposing it, apply it.
|
||||
if (fabsf(g_PosVelocity) < 1.0f || (g_PosVelocity * accel) < 0) {
|
||||
g_PosVelocity += accel;
|
||||
}
|
||||
|
||||
if ((friction > fabsf(g_PosVelocity)) && (friction > fabsf(accel))) {
|
||||
// Special get back to center and overcome friction physics.
|
||||
float t = tablePosNorm - 0.5f;
|
||||
if (fabsf(t) < (friction * g_DT)) {
|
||||
// really close, just snap
|
||||
g_PosPage = roundf(g_PosPage);
|
||||
g_PosVelocity = 0;
|
||||
} else {
|
||||
if (t > 0) {
|
||||
g_PosVelocity = -friction;
|
||||
} else {
|
||||
g_PosVelocity = friction;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal physics
|
||||
if (g_PosVelocity > 0) {
|
||||
g_PosVelocity -= friction;
|
||||
g_PosVelocity = maxf(g_PosVelocity, 0);
|
||||
} else {
|
||||
g_PosVelocity += friction;
|
||||
g_PosVelocity = minf(g_PosVelocity, 0);
|
||||
}
|
||||
}
|
||||
g_PosPage += g_PosVelocity * g_DT;
|
||||
|
||||
// Check for out of boundry conditions.
|
||||
if (g_PosPage < 0 && g_PosVelocity < 0) {
|
||||
float damp = 1.0 + (g_PosPage * 4);
|
||||
damp = clampf(damp, 0.f, 0.9f);
|
||||
g_PosVelocity *= damp;
|
||||
}
|
||||
if (g_PosPage > (g_PageCount-1) && g_PosVelocity > 0) {
|
||||
float damp = 1.0 - ((g_PosPage - g_PageCount + 1) * 4);
|
||||
damp = clampf(damp, 0.f, 0.9f);
|
||||
g_PosVelocity *= damp;
|
||||
}
|
||||
}
|
||||
|
||||
int positionStrip(float row, float column)
|
||||
{
|
||||
float mat1[16];
|
||||
|
||||
float y = 1.2f - row * 0.6f;
|
||||
|
||||
float scale = 256.f / getWidth();
|
||||
float xscale = scale * 4.55 / 1.8f / 2;
|
||||
|
||||
matrixLoadTranslate(mat1, 0.f, y, 0.f);
|
||||
matrixScale(mat1, 1.f, scale, 1.f);
|
||||
vpLoadModelMatrix(mat1);
|
||||
|
||||
float soff = -21.8f - (column * 1.25f);
|
||||
matrixLoadScale(mat1, xscale, 1.f, 1.f);
|
||||
matrixTranslate(mat1, soff, 0, 0);
|
||||
vpLoadTextureMatrix(mat1);
|
||||
|
||||
return - soff * 10.f;
|
||||
}
|
||||
|
||||
void drawIcon(float row, float column, int iconNum)
|
||||
{
|
||||
int offset = positionStrip(row, column);
|
||||
bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, iconNum));
|
||||
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
if (offset >= (450 - 20)) {
|
||||
offset = (449 - 20);
|
||||
}
|
||||
drawSimpleMeshRange(NAMED_SMMesh, offset * 6, 20 * 6);
|
||||
}
|
||||
|
||||
void
|
||||
draw_home_button()
|
||||
{
|
||||
color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
bindTexture(NAMED_PFTexLinear, 0, state->homeButtonId);
|
||||
|
||||
float scale = 2.0f / SCREEN_WIDTH_PX;
|
||||
|
||||
float x = 0.0f;
|
||||
|
||||
float y = -(SCREEN_HEIGHT_PX / (float)SCREEN_WIDTH_PX);
|
||||
y += g_Zoom * (scale * params->homeButtonTextureHeight / 2);
|
||||
|
||||
float z = 0.0f;
|
||||
drawSprite(x, y, z, params->homeButtonTextureWidth, params->homeButtonTextureHeight);
|
||||
}
|
||||
|
||||
int
|
||||
main(int launchID)
|
||||
{
|
||||
// Compute dt in seconds.
|
||||
int newTime = uptimeMillis();
|
||||
g_DT = (newTime - g_LastTime) / 1000.f;
|
||||
g_LastTime = newTime;
|
||||
|
||||
if (!g_DrawLastFrame) {
|
||||
// If we stopped rendering we cannot use DT.
|
||||
// assume 30fps in this case.
|
||||
g_DT = 0.033f;
|
||||
}
|
||||
if (g_DT > 0.2f) {
|
||||
// physics may break if DT is large.
|
||||
g_DT = 0.2f;
|
||||
}
|
||||
|
||||
debugF("zoom", g_Zoom);
|
||||
if (g_Zoom != state->zoomTarget) {
|
||||
float dz = (state->zoomTarget - g_Zoom) * g_DT * 5;
|
||||
if (dz && (fabsf(dz) < 0.03f)) {
|
||||
if (dz > 0) {
|
||||
dz = 0.03f;
|
||||
} else {
|
||||
dz = -0.03f;
|
||||
}
|
||||
}
|
||||
if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) {
|
||||
g_Zoom = state->zoomTarget;
|
||||
} else {
|
||||
g_Zoom += dz;
|
||||
}
|
||||
updateReadback();
|
||||
}
|
||||
|
||||
// Set clear value to dim the background based on the zoom position.
|
||||
if ((g_Zoom < 0.001f) && (state->zoomTarget < 0.001f)) {
|
||||
pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
// When we're zoomed out and not tracking motion events, reset the pos to 0.
|
||||
if (!g_LastTouchDown) {
|
||||
g_PosPage = 0;
|
||||
}
|
||||
return lastFrame(0);
|
||||
} else if (g_Zoom < 0.85f) {
|
||||
pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
|
||||
} else {
|
||||
pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
|
||||
}
|
||||
|
||||
// icons & labels
|
||||
int iconCount = state->iconCount;
|
||||
g_PageCount = count_pages(iconCount);
|
||||
|
||||
updatePos(0.1f);
|
||||
updateReadback();
|
||||
|
||||
debugF(" draw g_PosPage", g_PosPage);
|
||||
|
||||
// Draw the icons ========================================
|
||||
|
||||
// Bug makes 1.0f alpha fail.
|
||||
//color(0.2f, 0.2f, 0.2f, 0.99f);
|
||||
//bindProgramFragment(NAMED_PFColor);
|
||||
//positionStrip(0, 0);
|
||||
//drawSimpleMesh(NAMED_SMMesh);
|
||||
|
||||
bindProgramFragment(NAMED_PFTexLinear);
|
||||
|
||||
|
||||
int lastIcon = iconCount-1;
|
||||
|
||||
int page = g_PosPage;
|
||||
float currentPagePosition = g_PosPage - page;
|
||||
|
||||
int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
|
||||
float scale = (1 / g_Zoom);
|
||||
|
||||
float pageAngle = VIEW_ANGLE * 1.2f;
|
||||
|
||||
float zoomOffset = 40 * (1 - g_Zoom);
|
||||
int drawPage;
|
||||
//lastIcon = 1;
|
||||
for (drawPage = 0; drawPage < g_PageCount; drawPage++) {
|
||||
int r, c;
|
||||
for (r=0; r < 4; r++) {
|
||||
for (c=0; c < 4; c++) {
|
||||
int iconNum = drawPage * 16 + c + r * 4;
|
||||
if (iconNum <= lastIcon) {
|
||||
float p = (((float)drawPage) - g_PosPage) * 5.f;
|
||||
p += c - 1.5f;
|
||||
p += zoomOffset;
|
||||
if (fabsf(p) > 2) {
|
||||
drawIcon(r, p, iconNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (drawPage = 0; drawPage < g_PageCount; drawPage++) {
|
||||
int r, c;
|
||||
for (r=0; r < 4; r++) {
|
||||
for (c=0; c < 4; c++) {
|
||||
int iconNum = drawPage * 16 + c + r * 4;
|
||||
if (iconNum <= lastIcon) {
|
||||
float p = (((float)drawPage) - g_PosPage) * 5.f;
|
||||
p += c - 1.5f;
|
||||
p += zoomOffset;
|
||||
float x = (p * 1.13f + 1.88f) * getWidth() * 0.2f;
|
||||
float y = 570 - r * 147;
|
||||
|
||||
if (fabsf(p) <= 2) {
|
||||
drawIcon(r, p, iconNum);
|
||||
}
|
||||
if (fabsf(p) <= 2.5) {
|
||||
float a = (1.2f - maxf(scale, 1.0f)) * 5;
|
||||
color(1.0f, 1.0f, 1.0f, a);
|
||||
bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_LABEL_IDS, iconNum));
|
||||
drawSpriteScreenspace(x, y, 0,
|
||||
params->bubbleBitmapWidth, params->bubbleBitmapHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
float mat1[16];
|
||||
matrixLoadIdentity(mat1);
|
||||
vpLoadModelMatrix(mat1);
|
||||
vpLoadTextureMatrix(mat1);
|
||||
}
|
||||
|
||||
// Draw the home button ========================================
|
||||
//draw_home_button();
|
||||
|
||||
// Bug workaround where the last frame is not always displayed
|
||||
// So we keep rendering until the bug is fixed.
|
||||
return 1; //(g_PosVelocity != 0) || fracf(g_PosPage) || g_Zoom != g_ZoomTarget);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,5 @@
|
||||
<string name="permdesc_read_settings" msgid="8377434937176025492">"Tillader, at et program læser indstillingerne og genvejene i Start."</string>
|
||||
<string name="permlab_write_settings" msgid="1360567537236705628">"skriv indstillinger og genveje for Start"</string>
|
||||
<string name="permdesc_write_settings" msgid="1098648778383349818">"Tillader, at et program ændrer indstillingerne og genvejene i Start."</string>
|
||||
<string name="search_hint" msgid="6974176141372467453">"Google-søgning"</string>
|
||||
<string name="gadget_error_text" msgid="8359351016167075858">"Der er problemer med indlæsning af widget"</string>
|
||||
</resources>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
<resources>
|
||||
<dimen name="workspace_cell_width">106dip</dimen>
|
||||
<dimen name="workspace_cell_height">74dip</dimen>
|
||||
<dimen name="button_bar_height">62dip</dimen>
|
||||
<dimen name="search_widget_inset">19dip</dimen>
|
||||
<dimen name="gesture_thumbnail_inset">8dip</dimen>
|
||||
<dimen name="gesture_thumbnail_size">64dip</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
<string name="add_folder" msgid="3521088587367839879">"文件夹"</string>
|
||||
<string name="add_clock" msgid="2337943840175865746">"时钟"</string>
|
||||
<string name="add_photo_frame" msgid="3154058437359487954">"相框"</string>
|
||||
<string name="add_search" msgid="7104834713685095105">"搜索"</string>
|
||||
<string name="out_of_space" msgid="8365249326091984698">"此主屏幕上已没有空间。"</string>
|
||||
<string name="add_search" msgid="7104834713685095105">"搜索"</string>
|
||||
<string name="shortcut_installed" msgid="7071557296331322355">"已创建“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
|
||||
<string name="shortcut_uninstalled" msgid="2129499669449749995">"已删除“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
|
||||
<string name="shortcut_duplicate" msgid="4757756326465060694">"“<xliff:g id="NAME">%s</xliff:g>”快捷方式已存在。"</string>
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<dimen name="title_texture_width">120px</dimen>
|
||||
<dimen name="search_widget_inset">19dip</dimen>
|
||||
<dimen name="gesture_thumbnail_inset">8dip</dimen>
|
||||
<dimen name="gesture_thumbnail_size">64dip</dimen>
|
||||
<dimen name="button_bar_height">56dip</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -1,405 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import com.android.internal.app.AlertActivity;
|
||||
import com.android.internal.app.AlertController;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.Intent.ShortcutIconResource;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.PaintDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Displays a list of all activities matching the incoming
|
||||
* {@link android.content.Intent#EXTRA_INTENT} query, along with any injected items.
|
||||
*/
|
||||
public class ActivityPicker extends AlertActivity implements
|
||||
DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
|
||||
|
||||
/**
|
||||
* Adapter of items that are displayed in this dialog.
|
||||
*/
|
||||
private PickAdapter mAdapter;
|
||||
|
||||
/**
|
||||
* Base {@link android.content.Intent} used when building list.
|
||||
*/
|
||||
private Intent mBaseIntent;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Intent intent = getIntent();
|
||||
|
||||
// Read base intent from extras, otherwise assume default
|
||||
Parcelable parcel = intent.getParcelableExtra(Intent.EXTRA_INTENT);
|
||||
if (parcel instanceof Intent) {
|
||||
mBaseIntent = (Intent) parcel;
|
||||
} else {
|
||||
mBaseIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||
mBaseIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
}
|
||||
|
||||
// Create dialog parameters
|
||||
AlertController.AlertParams params = mAlertParams;
|
||||
params.mOnClickListener = this;
|
||||
params.mOnCancelListener = this;
|
||||
|
||||
// Use custom title if provided, otherwise default window title
|
||||
if (intent.hasExtra(Intent.EXTRA_TITLE)) {
|
||||
params.mTitle = intent.getStringExtra(Intent.EXTRA_TITLE);
|
||||
} else {
|
||||
params.mTitle = getTitle();
|
||||
}
|
||||
|
||||
// Build list adapter of pickable items
|
||||
List<PickAdapter.Item> items = getItems();
|
||||
mAdapter = new PickAdapter(this, items);
|
||||
params.mAdapter = mAdapter;
|
||||
|
||||
setupAlert();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle clicking of dialog item by passing back
|
||||
* {@link #getIntentForPosition(int)} in {@link #setResult(int, android.content.Intent)}.
|
||||
*/
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = getIntentForPosition(which);
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle canceled dialog by passing back {@link android.app.Activity#RESULT_CANCELED}.
|
||||
*/
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
setResult(Activity.RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the specific {@link android.content.Intent} for a given list position. Convenience
|
||||
* method that calls through to {@link PickAdapter.Item#getIntent(android.content.Intent)}.
|
||||
*/
|
||||
protected Intent getIntentForPosition(int position) {
|
||||
PickAdapter.Item item = (PickAdapter.Item) mAdapter.getItem(position);
|
||||
return item.getIntent(mBaseIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return list of items to be shown in dialog. Default
|
||||
* implementation mixes activities matching {@link #mBaseIntent} from
|
||||
* {@link #putIntentItems(android.content.Intent, java.util.List)} with any injected items from
|
||||
* {@link android.content.Intent#EXTRA_SHORTCUT_NAME}. Override this method in subclasses to
|
||||
* change the items shown.
|
||||
*/
|
||||
protected List<PickAdapter.Item> getItems() {
|
||||
PackageManager packageManager = getPackageManager();
|
||||
List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
|
||||
|
||||
// Add any injected pick items
|
||||
final Intent intent = getIntent();
|
||||
ArrayList<String> labels =
|
||||
intent.getStringArrayListExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
ArrayList<ShortcutIconResource> icons =
|
||||
intent.getParcelableArrayListExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
|
||||
|
||||
if (labels != null && icons != null && labels.size() == icons.size()) {
|
||||
for (int i = 0; i < labels.size(); i++) {
|
||||
String label = labels.get(i);
|
||||
Drawable icon = null;
|
||||
|
||||
try {
|
||||
// Try loading icon from requested package
|
||||
ShortcutIconResource iconResource = icons.get(i);
|
||||
Resources res = packageManager.getResourcesForApplication(
|
||||
iconResource.packageName);
|
||||
icon = res.getDrawable(res.getIdentifier(
|
||||
iconResource.resourceName, null, null));
|
||||
} catch (NameNotFoundException e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
items.add(new PickAdapter.Item(this, label, icon));
|
||||
}
|
||||
}
|
||||
|
||||
// Add any intent items if base was given
|
||||
if (mBaseIntent != null) {
|
||||
putIntentItems(mBaseIntent, items);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the given list with any activities matching the base {@link android.content.Intent}.
|
||||
*/
|
||||
protected void putIntentItems(Intent baseIntent, List<PickAdapter.Item> items) {
|
||||
PackageManager packageManager = getPackageManager();
|
||||
List<ResolveInfo> list = packageManager.queryIntentActivities(baseIntent,
|
||||
0 /* no flags */);
|
||||
Collections.sort(list, new ResolveInfo.DisplayNameComparator(packageManager));
|
||||
|
||||
final int listSize = list.size();
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
ResolveInfo resolveInfo = list.get(i);
|
||||
items.add(new PickAdapter.Item(this, packageManager, resolveInfo));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter which shows the set of activities that can be performed for a
|
||||
* given {@link android.content.Intent}.
|
||||
*/
|
||||
protected static class PickAdapter extends BaseAdapter {
|
||||
|
||||
/**
|
||||
* Item that appears in a {@link PickAdapter} list.
|
||||
*/
|
||||
public static class Item {
|
||||
protected static IconResizer sResizer;
|
||||
|
||||
protected IconResizer getResizer(Context context) {
|
||||
if (sResizer == null) {
|
||||
sResizer = new IconResizer(context);
|
||||
}
|
||||
return sResizer;
|
||||
}
|
||||
|
||||
CharSequence label;
|
||||
Drawable icon;
|
||||
String packageName;
|
||||
String className;
|
||||
Bundle extras;
|
||||
|
||||
/**
|
||||
* Create a list item from given label and icon.
|
||||
*/
|
||||
Item(Context context, CharSequence label, Drawable icon) {
|
||||
this.label = label;
|
||||
this.icon = getResizer(context).createIconThumbnail(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list item and fill it with details from the given
|
||||
* {@link android.content.pm.ResolveInfo} object.
|
||||
*/
|
||||
Item(Context context, PackageManager pm, ResolveInfo resolveInfo) {
|
||||
label = resolveInfo.loadLabel(pm);
|
||||
if (label == null && resolveInfo.activityInfo != null) {
|
||||
label = resolveInfo.activityInfo.name;
|
||||
}
|
||||
|
||||
icon = getResizer(context).createIconThumbnail(resolveInfo.loadIcon(pm));
|
||||
packageName = resolveInfo.activityInfo.applicationInfo.packageName;
|
||||
className = resolveInfo.activityInfo.name;
|
||||
}
|
||||
|
||||
Intent getIntent(Intent baseIntent) {
|
||||
Intent intent = new Intent(baseIntent);
|
||||
if (packageName != null && className != null) {
|
||||
// Valid package and class, so fill details as normal intent
|
||||
intent.setClassName(packageName, className);
|
||||
if (extras != null) {
|
||||
intent.putExtras(extras);
|
||||
}
|
||||
} else {
|
||||
// No valid package or class, so treat as shortcut with label
|
||||
intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
private List<Item> mItems;
|
||||
private int mLayoutRes = R.layout.pick_item;
|
||||
|
||||
/**
|
||||
* Create an adapter for the given items.
|
||||
*/
|
||||
public PickAdapter(Context context, List<Item> items) {
|
||||
mInflater = (LayoutInflater)
|
||||
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mItems = items;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getCount() {
|
||||
return mItems.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getItem(int position) {
|
||||
return mItems.get(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(mLayoutRes, parent, false);
|
||||
}
|
||||
|
||||
Item item = (Item) getItem(position);
|
||||
TextView textView = (TextView) convertView;
|
||||
textView.setText(item.label);
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to resize icons to match default icon size. Code is mostly
|
||||
* borrowed from Launcher.
|
||||
*/
|
||||
private static class IconResizer {
|
||||
private int mIconWidth = -1;
|
||||
private int mIconHeight = -1;
|
||||
|
||||
private final Rect mOldBounds = new Rect();
|
||||
private Canvas mCanvas = new Canvas();
|
||||
private Resources mResources;
|
||||
|
||||
public IconResizer(Context context) {
|
||||
mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
|
||||
Paint.FILTER_BITMAP_FLAG));
|
||||
|
||||
mResources = context.getResources();
|
||||
mIconWidth = mIconHeight = (int) mResources.getDimension(
|
||||
android.R.dimen.app_icon_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Drawable representing the thumbnail of the specified Drawable.
|
||||
* The size of the thumbnail is defined by the dimension
|
||||
* android.R.dimen.launcher_application_icon_size.
|
||||
*
|
||||
* This method is not thread-safe and should be invoked on the UI thread only.
|
||||
*
|
||||
* @param icon The icon to get a thumbnail of.
|
||||
*
|
||||
* @return A thumbnail for the specified icon or the icon itself if the
|
||||
* thumbnail could not be created.
|
||||
*/
|
||||
public Drawable createIconThumbnail(Drawable icon) {
|
||||
int width = mIconWidth;
|
||||
int height = mIconHeight;
|
||||
|
||||
if (icon == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int iconWidth = icon.getIntrinsicWidth();
|
||||
final int iconHeight = icon.getIntrinsicHeight();
|
||||
|
||||
if (icon instanceof PaintDrawable) {
|
||||
PaintDrawable painter = (PaintDrawable) icon;
|
||||
painter.setIntrinsicWidth(width);
|
||||
painter.setIntrinsicHeight(height);
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
if (width < iconWidth || height < iconHeight) {
|
||||
final float ratio = (float) iconWidth / iconHeight;
|
||||
|
||||
if (iconWidth > iconHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (iconHeight > iconWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
|
||||
final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
|
||||
Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
|
||||
final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
|
||||
final Canvas canvas = mCanvas;
|
||||
canvas.setBitmap(thumb);
|
||||
// Copy the old bounds to restore them later
|
||||
// If we were to do oldBounds = icon.getBounds(),
|
||||
// the call to setBounds() that follows would
|
||||
// change the same instance and we would lose the
|
||||
// old bounds
|
||||
mOldBounds.set(icon.getBounds());
|
||||
final int x = (mIconWidth - width) / 2;
|
||||
final int y = (mIconHeight - height) / 2;
|
||||
icon.setBounds(x, y, x + width, y + height);
|
||||
icon.draw(canvas);
|
||||
icon.setBounds(mOldBounds);
|
||||
icon = new BitmapDrawable(mResources, thumb);
|
||||
} else if (iconWidth < width && iconHeight < height) {
|
||||
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
|
||||
final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
|
||||
final Canvas canvas = mCanvas;
|
||||
canvas.setBitmap(thumb);
|
||||
mOldBounds.set(icon.getBounds());
|
||||
final int x = (width - iconWidth) / 2;
|
||||
final int y = (height - iconHeight) / 2;
|
||||
icon.setBounds(x, y, x + iconWidth, y + iconHeight);
|
||||
icon.draw(canvas);
|
||||
icon.setBounds(mOldBounds);
|
||||
icon = new BitmapDrawable(mResources, thumb);
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,25 +17,13 @@
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.os.Process;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -46,18 +34,23 @@ class AllAppsList {
|
||||
public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
|
||||
|
||||
/** The list off all apps. */
|
||||
public ArrayList<ApplicationInfo> data = new ArrayList(DEFAULT_APPLICATIONS_NUMBER);
|
||||
public ArrayList<ApplicationInfo> data =
|
||||
new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
|
||||
/** The list of apps that have been added since the last notify() call. */
|
||||
public ArrayList<ApplicationInfo> added = new ArrayList(DEFAULT_APPLICATIONS_NUMBER);
|
||||
public ArrayList<ApplicationInfo> added =
|
||||
new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
|
||||
/** The list of apps that have been removed since the last notify() call. */
|
||||
public ArrayList<ApplicationInfo> removed = new ArrayList();
|
||||
public ArrayList<ApplicationInfo> removed = new ArrayList<ApplicationInfo>();
|
||||
/** The list of apps that have been modified since the last notify() call. */
|
||||
public ArrayList<ApplicationInfo> modified = new ArrayList();
|
||||
public ArrayList<ApplicationInfo> modified = new ArrayList<ApplicationInfo>();
|
||||
|
||||
private IconCache mIconCache;
|
||||
|
||||
/**
|
||||
* Boring constructor.
|
||||
*/
|
||||
public AllAppsList() {
|
||||
public AllAppsList(IconCache iconCache) {
|
||||
mIconCache = iconCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,9 +85,8 @@ class AllAppsList {
|
||||
final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
|
||||
|
||||
if (matches.size() > 0) {
|
||||
Utilities.BubbleText bubble = new Utilities.BubbleText(context);
|
||||
for (ResolveInfo info : matches) {
|
||||
ApplicationInfo item = AppInfoCache.cache(info, context, bubble);
|
||||
ApplicationInfo item = new ApplicationInfo(info, mIconCache);
|
||||
data.add(item);
|
||||
added.add(item);
|
||||
}
|
||||
@@ -106,7 +98,7 @@ class AllAppsList {
|
||||
*/
|
||||
public void removePackage(String packageName) {
|
||||
final List<ApplicationInfo> data = this.data;
|
||||
for (int i=data.size()-1; i>=0; i--) {
|
||||
for (int i = data.size() - 1; i >= 0; i--) {
|
||||
ApplicationInfo info = data.get(i);
|
||||
final ComponentName component = info.intent.getComponent();
|
||||
if (packageName.equals(component.getPackageName())) {
|
||||
@@ -115,9 +107,9 @@ class AllAppsList {
|
||||
}
|
||||
}
|
||||
// This is more aggressive than it needs to be.
|
||||
AppInfoCache.flush();
|
||||
mIconCache.flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add and remove icons for this package which has been updated.
|
||||
*/
|
||||
@@ -126,13 +118,13 @@ class AllAppsList {
|
||||
if (matches.size() > 0) {
|
||||
// Find disabled/removed activities and remove them from data and add them
|
||||
// to the removed list.
|
||||
for (int i=data.size()-1; i>=0; i--) {
|
||||
for (int i = data.size() - 1; i >= 0; i--) {
|
||||
final ApplicationInfo applicationInfo = data.get(i);
|
||||
final ComponentName component = applicationInfo.intent.getComponent();
|
||||
if (packageName.equals(component.getPackageName())) {
|
||||
if (!findActivity(matches, component)) {
|
||||
removed.add(applicationInfo);
|
||||
AppInfoCache.remove(component);
|
||||
mIconCache.remove(component);
|
||||
data.remove(i);
|
||||
}
|
||||
}
|
||||
@@ -140,19 +132,19 @@ class AllAppsList {
|
||||
|
||||
// Find enabled activities and add them to the adapter
|
||||
// Also updates existing activities with new labels/icons
|
||||
Utilities.BubbleText bubble = new Utilities.BubbleText(context);
|
||||
int count = matches.size();
|
||||
for (int i=0; i<count; i++) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
final ResolveInfo info = matches.get(i);
|
||||
ApplicationInfo applicationInfo = findApplicationInfoLocked(
|
||||
info.activityInfo.applicationInfo.packageName,
|
||||
info.activityInfo.name);
|
||||
if (applicationInfo == null) {
|
||||
applicationInfo = AppInfoCache.cache(info, context, bubble);
|
||||
applicationInfo = new ApplicationInfo(info, mIconCache);
|
||||
data.add(applicationInfo);
|
||||
added.add(applicationInfo);
|
||||
} else {
|
||||
AppInfoCache.update(info, applicationInfo, context, bubble);
|
||||
mIconCache.remove(applicationInfo.componentName);
|
||||
mIconCache.getTitleAndIcon(applicationInfo, info);
|
||||
modified.add(applicationInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,8 +114,10 @@ public class AllAppsView extends RSSurfaceView
|
||||
|
||||
private boolean mShouldGainFocus;
|
||||
|
||||
private boolean mHaveSurface = false;
|
||||
private boolean mZoomDirty = false;
|
||||
private boolean mAnimateNextZoom;
|
||||
private float mNextZoom;
|
||||
private float mZoom;
|
||||
private float mPosX;
|
||||
private float mVelocity;
|
||||
@@ -125,20 +127,19 @@ public class AllAppsView extends RSSurfaceView
|
||||
public static final int ALLOC_PARAMS = 0;
|
||||
public static final int ALLOC_STATE = 1;
|
||||
public static final int ALLOC_ICON_IDS = 3;
|
||||
public static final int ALLOC_LABEL_IDS = 4;
|
||||
public static final int ALLOC_VP_CONSTANTS = 5;
|
||||
|
||||
public static final int COLUMNS_PER_PAGE = 4;
|
||||
public static final int ROWS_PER_PAGE = 4;
|
||||
|
||||
public static final int ICON_TEXTURE_WIDTH_PX = 128;
|
||||
public static final int ICON_TEXTURE_HEIGHT_PX = 128;
|
||||
public static final int ICON_WIDTH_PX = 64;
|
||||
public static final int ICON_TEXTURE_WIDTH_PX = 74;
|
||||
public static final int SELECTION_TEXTURE_WIDTH_PX = 74 + 20;
|
||||
|
||||
public int SCREEN_WIDTH_PX;
|
||||
public int SCREEN_HEIGHT_PX;
|
||||
|
||||
public void recompute(int w, int h) {
|
||||
SCREEN_WIDTH_PX = 480;
|
||||
SCREEN_HEIGHT_PX = 800;
|
||||
}
|
||||
public static final int ICON_HEIGHT_PX = 64;
|
||||
public static final int ICON_TEXTURE_HEIGHT_PX = 74;
|
||||
public static final int SELECTION_TEXTURE_HEIGHT_PX = 74 + 20;
|
||||
}
|
||||
|
||||
public AllAppsView(Context context, AttributeSet attrs) {
|
||||
@@ -158,9 +159,14 @@ public class AllAppsView extends RSSurfaceView
|
||||
mRS = createRenderScript(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that this implementation prohibits this view from ever being reattached.
|
||||
*/
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
destroyRenderScript();
|
||||
mRS.mMessageCallback = null;
|
||||
mRS = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,9 +191,12 @@ public class AllAppsView extends RSSurfaceView
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
super.surfaceDestroyed(holder);
|
||||
mRollo.mHasSurface = false;
|
||||
// Without this, we leak mMessageCallback which leaks the context.
|
||||
mRS.mMessageCallback = null;
|
||||
// We may lose any callbacks that are pending, so make sure that we re-sync that
|
||||
// on the next surfaceChanged.
|
||||
mZoomDirty = true;
|
||||
mHaveSurface = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -196,9 +205,10 @@ public class AllAppsView extends RSSurfaceView
|
||||
|
||||
super.surfaceChanged(holder, format, w, h);
|
||||
|
||||
mHaveSurface = true;
|
||||
|
||||
if (mRollo == null) {
|
||||
mRollo = new RolloRS();
|
||||
mRollo.mHasSurface = true;
|
||||
mRollo.init(getResources(), w, h);
|
||||
if (mAllAppsList != null) {
|
||||
mRollo.setApps(mAllAppsList);
|
||||
@@ -207,17 +217,34 @@ public class AllAppsView extends RSSurfaceView
|
||||
gainFocus();
|
||||
mShouldGainFocus = false;
|
||||
}
|
||||
} else {
|
||||
mRollo.mHasSurface = true;
|
||||
}
|
||||
mRollo.dirtyCheck();
|
||||
mRollo.resize(w, h);
|
||||
|
||||
mRS.mMessageCallback = mMessageProc = new AAMessage();
|
||||
if (mRS != null) {
|
||||
mRS.mMessageCallback = mMessageProc = new AAMessage();
|
||||
}
|
||||
|
||||
Resources res = getContext().getResources();
|
||||
int barHeight = (int)res.getDimension(R.dimen.button_bar_height);
|
||||
|
||||
|
||||
if (mRollo.mUniformAlloc != null) {
|
||||
float tf[] = new float[] {72.f, 72.f,
|
||||
120.f, 120.f, 0.f, 0.f,
|
||||
120.f, 680.f,
|
||||
(2.f / 480.f), 0, -((float)w / 2) - 0.25f, -380.25f};
|
||||
if (w > h) {
|
||||
tf[6] = 40.f;
|
||||
tf[7] = h - 40.f;
|
||||
tf[9] = 1.f;
|
||||
tf[10] = -((float)w / 2) - 0.25f;
|
||||
tf[11] = -((float)h / 2) - 0.25f;
|
||||
}
|
||||
|
||||
mRollo.mUniformAlloc.data(tf);
|
||||
}
|
||||
|
||||
//long endTime = SystemClock.uptimeMillis();
|
||||
//Log.d(TAG, "surfaceChanged took " + (endTime-startTime) + "ms");
|
||||
}
|
||||
@@ -267,7 +294,7 @@ public class AllAppsView extends RSSurfaceView
|
||||
}
|
||||
|
||||
if (gainFocus) {
|
||||
if (mRollo != null && mRollo.mHasSurface) {
|
||||
if (mRollo != null) {
|
||||
gainFocus();
|
||||
} else {
|
||||
mShouldGainFocus = true;
|
||||
@@ -402,15 +429,19 @@ public class AllAppsView extends RSSurfaceView
|
||||
break;
|
||||
}
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
if (currentPageCol > 0) {
|
||||
newSelection = currentSelection - 1;
|
||||
if (mLastSelection != SELECTION_HOME) {
|
||||
if (currentPageCol > 0) {
|
||||
newSelection = currentSelection - 1;
|
||||
}
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
if ((currentPageCol < Defines.COLUMNS_PER_PAGE - 1) &&
|
||||
(currentSelection < iconCount - 1)) {
|
||||
newSelection = currentSelection + 1;
|
||||
if (mLastSelection != SELECTION_HOME) {
|
||||
if ((currentPageCol < Defines.COLUMNS_PER_PAGE - 1) &&
|
||||
(currentSelection < iconCount - 1)) {
|
||||
newSelection = currentSelection + 1;
|
||||
}
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
@@ -567,8 +598,7 @@ public class AllAppsView extends RSSurfaceView
|
||||
&& mCurrentIconIndex >= 0 && mCurrentIconIndex < mAllAppsList.size()) {
|
||||
ApplicationInfo app = mAllAppsList.get(mCurrentIconIndex);
|
||||
|
||||
Bitmap bmp = Utilities.extractIconFromTexture(app.iconBitmap, getContext());
|
||||
|
||||
Bitmap bmp = app.iconBitmap;
|
||||
final int w = bmp.getWidth();
|
||||
final int h = bmp.getHeight();
|
||||
|
||||
@@ -576,9 +606,10 @@ public class AllAppsView extends RSSurfaceView
|
||||
int screenX = mMotionDownRawX - (w / 2);
|
||||
int screenY = mMotionDownRawY - h;
|
||||
|
||||
int left = (mDefines.ICON_TEXTURE_WIDTH_PX - mDefines.ICON_WIDTH_PX) / 2;
|
||||
int top = (mDefines.ICON_TEXTURE_HEIGHT_PX - mDefines.ICON_HEIGHT_PX) / 2;
|
||||
mDragController.startDrag(bmp, screenX, screenY,
|
||||
0, 0, w, h, this, app, DragController.DRAG_ACTION_COPY);
|
||||
bmp.recycle();
|
||||
|
||||
mLauncher.closeAllApps(true);
|
||||
}
|
||||
@@ -636,10 +667,13 @@ public class AllAppsView extends RSSurfaceView
|
||||
*/
|
||||
public void zoom(float zoom, boolean animate) {
|
||||
cancelLongPress();
|
||||
if (mRollo == null || !mRollo.mHasSurface) {
|
||||
mNextZoom = zoom;
|
||||
mAnimateNextZoom = animate;
|
||||
// if we do setZoom while we don't have a surface, we won't
|
||||
// get the callbacks that actually set mZoom.
|
||||
if (mRollo == null || !mHaveSurface) {
|
||||
mZoomDirty = true;
|
||||
mZoom = zoom;
|
||||
mAnimateNextZoom = animate;
|
||||
return;
|
||||
} else {
|
||||
mRollo.setZoom(zoom, animate);
|
||||
@@ -655,6 +689,11 @@ public class AllAppsView extends RSSurfaceView
|
||||
}
|
||||
|
||||
public void setApps(ArrayList<ApplicationInfo> list) {
|
||||
if (mRS == null) {
|
||||
// We've been removed from the window. Don't bother with all this.
|
||||
return;
|
||||
}
|
||||
|
||||
mAllAppsList = list;
|
||||
if (mRollo != null) {
|
||||
mRollo.setApps(list);
|
||||
@@ -667,6 +706,10 @@ public class AllAppsView extends RSSurfaceView
|
||||
// Not done loading yet. We'll find out about it later.
|
||||
return;
|
||||
}
|
||||
if (mRS == null) {
|
||||
// We've been removed from the window. Don't bother with all this.
|
||||
return;
|
||||
}
|
||||
|
||||
final int N = list.size();
|
||||
if (mRollo != null) {
|
||||
@@ -769,16 +812,16 @@ public class AllAppsView extends RSSurfaceView
|
||||
private Script.Invokable mInvokeSetZoom;
|
||||
|
||||
private ProgramStore mPSIcons;
|
||||
private ProgramStore mPSText;
|
||||
private ProgramFragment mPFColor;
|
||||
private ProgramFragment mPFTexMip;
|
||||
private ProgramFragment mPFTexMipAlpha;
|
||||
private ProgramFragment mPFTexNearest;
|
||||
private ProgramVertex mPV;
|
||||
private ProgramVertex mPVOrtho;
|
||||
private ProgramVertex mPVCurve;
|
||||
private SimpleMesh mMesh;
|
||||
private SimpleMesh mMesh2;
|
||||
private ProgramVertex.MatrixAllocation mPVA;
|
||||
|
||||
private Allocation mUniformAlloc;
|
||||
|
||||
private Allocation mHomeButtonNormal;
|
||||
private Allocation mHomeButtonFocused;
|
||||
private Allocation mHomeButtonPressed;
|
||||
@@ -786,6 +829,10 @@ public class AllAppsView extends RSSurfaceView
|
||||
private Allocation[] mIcons;
|
||||
private int[] mIconIds;
|
||||
private Allocation mAllocIconIds;
|
||||
|
||||
private Allocation[] mLabels;
|
||||
private int[] mLabelIds;
|
||||
private Allocation mAllocLabelIds;
|
||||
private Allocation mSelectedIcon;
|
||||
|
||||
private int[] mTouchYBorders;
|
||||
@@ -794,9 +841,6 @@ public class AllAppsView extends RSSurfaceView
|
||||
private Bitmap mSelectionBitmap;
|
||||
private Canvas mSelectionCanvas;
|
||||
|
||||
boolean mHasSurface = false;
|
||||
private boolean mAppsDirty = true;
|
||||
|
||||
Params mParams;
|
||||
State mState;
|
||||
|
||||
@@ -856,11 +900,9 @@ public class AllAppsView extends RSSurfaceView
|
||||
mRes = res;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mDefines.recompute(width, height);
|
||||
initProgramVertex();
|
||||
initProgramFragment();
|
||||
initProgramStore();
|
||||
initMesh();
|
||||
initGl();
|
||||
initData();
|
||||
initTouchState();
|
||||
@@ -868,41 +910,19 @@ public class AllAppsView extends RSSurfaceView
|
||||
}
|
||||
|
||||
public void initMesh() {
|
||||
SimpleMesh.TriangleMeshBuilder tm = new SimpleMesh.TriangleMeshBuilder(mRS, 3,
|
||||
SimpleMesh.TriangleMeshBuilder.TEXTURE_0 | SimpleMesh.TriangleMeshBuilder.COLOR);
|
||||
SimpleMesh.TriangleMeshBuilder tm = new SimpleMesh.TriangleMeshBuilder(mRS, 2, 0);
|
||||
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
for (int ct=0; ct < 200; ct++) {
|
||||
float angle = 0;
|
||||
float maxAngle = 3.14f * 0.16f;
|
||||
float l = 1.f;
|
||||
|
||||
l = 1 - ((ct-7) * 0.10f);
|
||||
if (ct > 7) {
|
||||
angle = maxAngle * (ct - 7) * 0.2f;
|
||||
angle = Math.min(angle, maxAngle);
|
||||
}
|
||||
l = Math.max(0.4f, l);
|
||||
l = Math.min(1.0f, l);
|
||||
|
||||
y += 0.1f * Math.cos(angle);
|
||||
z += 0.1f * Math.sin(angle);
|
||||
|
||||
float t = 0.1f * ct;
|
||||
float ds = 0.08f;
|
||||
tm.setColor(l, l, l, 0.99f);
|
||||
tm.setTexture(ds, t);
|
||||
tm.addVertex(-0.5f, y, z);
|
||||
tm.setTexture(1 - ds, t);
|
||||
tm.addVertex(0.5f, y, z);
|
||||
for (int ct=0; ct < 16; ct++) {
|
||||
float pos = (1.f / (16.f - 1)) * ct;
|
||||
tm.addVertex(0.0f, pos);
|
||||
tm.addVertex(1.0f, pos);
|
||||
}
|
||||
for (int ct=0; ct < (200 * 2 - 2); ct+= 2) {
|
||||
for (int ct=0; ct < (16 * 2 - 2); ct+= 2) {
|
||||
tm.addTriangle(ct, ct+1, ct+2);
|
||||
tm.addTriangle(ct+1, ct+3, ct+2);
|
||||
}
|
||||
mMesh2 = tm.create();
|
||||
mMesh2.setName("SMMesh");
|
||||
mMesh = tm.create();
|
||||
mMesh.setName("SMCell");
|
||||
}
|
||||
|
||||
void resize(int w, int h) {
|
||||
@@ -921,12 +941,80 @@ public class AllAppsView extends RSSurfaceView
|
||||
mPV.setName("PV");
|
||||
mPV.bindAllocation(mPVA);
|
||||
|
||||
//pva = new ProgramVertex.MatrixAllocation(mRS);
|
||||
//pva.setupOrthoWindow(mWidth, mHeight);
|
||||
//pvb.setTextureMatrixEnable(true);
|
||||
//mPVOrtho = pvb.create();
|
||||
//mPVOrtho.setName("PVOrtho");
|
||||
//mPVOrtho.bindAllocation(pva);
|
||||
Element.Builder eb = new Element.Builder(mRS);
|
||||
eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "ImgSize");
|
||||
eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Position");
|
||||
eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 2), "BendPos");
|
||||
eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "ScaleOffset");
|
||||
Element e = eb.create();
|
||||
|
||||
mUniformAlloc = Allocation.createSized(mRS, e, 1);
|
||||
|
||||
initMesh();
|
||||
ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
|
||||
String t = new String("void main() {\n" +
|
||||
// Animation
|
||||
" float ani = UNI_Position.z;\n" +
|
||||
|
||||
" float bendY1 = UNI_BendPos.x;\n" +
|
||||
" float bendY2 = UNI_BendPos.y;\n" +
|
||||
" float bendAngle = 47.0 * (3.14 / 180.0);\n" +
|
||||
" float bendDistance = bendY1 * 0.4;\n" +
|
||||
" float distanceDimLevel = 0.6;\n" +
|
||||
|
||||
" float bendStep = (bendAngle / bendDistance) * (bendAngle * 0.5);\n" +
|
||||
" float aDy = cos(bendAngle);\n" +
|
||||
" float aDz = sin(bendAngle);\n" +
|
||||
|
||||
" float scale = (2.0 / 480.0);\n" +
|
||||
" float x = UNI_Position.x + UNI_ImgSize.x * (1.0 - ani) * (ATTRIB_position.x - 0.5);\n" +
|
||||
" float ys= UNI_Position.y + UNI_ImgSize.y * (1.0 - ani) * ATTRIB_position.y;\n" +
|
||||
" float y = 0.0;\n" +
|
||||
" float z = 0.0;\n" +
|
||||
" float lum = 1.0;\n" +
|
||||
|
||||
" float cv = min(ys, bendY1 - bendDistance) - (bendY1 - bendDistance);\n" +
|
||||
" y += cv * aDy;\n" +
|
||||
" z += -cv * aDz;\n" +
|
||||
" cv = clamp(ys, bendY1 - bendDistance, bendY1) - bendY1;\n" + // curve range
|
||||
" lum += cv / bendDistance * distanceDimLevel;\n" +
|
||||
" y += cv * cos(cv * bendStep);\n" +
|
||||
" z += cv * sin(cv * bendStep);\n" +
|
||||
|
||||
" cv = max(ys, bendY2 + bendDistance) - (bendY2 + bendDistance);\n" +
|
||||
" y += cv * aDy;\n" +
|
||||
" z += cv * aDz;\n" +
|
||||
" cv = clamp(ys, bendY2, bendY2 + bendDistance) - bendY2;\n" +
|
||||
" lum -= cv / bendDistance * distanceDimLevel;\n" +
|
||||
" y += cv * cos(cv * bendStep);\n" +
|
||||
" z += cv * sin(cv * bendStep);\n" +
|
||||
|
||||
" y += clamp(ys, bendY1, bendY2);\n" +
|
||||
|
||||
" vec4 pos;\n" +
|
||||
" pos.x = (x + UNI_ScaleOffset.z) * UNI_ScaleOffset.x;\n" +
|
||||
" pos.y = (y + UNI_ScaleOffset.w) * UNI_ScaleOffset.x;\n" +
|
||||
" pos.z = z * UNI_ScaleOffset.x;\n" +
|
||||
" pos.w = 1.0;\n" +
|
||||
|
||||
" pos.x *= 1.0 + ani * 4.0;\n" +
|
||||
" pos.y *= 1.0 + ani * 4.0;\n" +
|
||||
" pos.z -= ani * 1.5;\n" +
|
||||
" lum *= 1.0 - ani;\n" +
|
||||
|
||||
" gl_Position = UNI_MVP * pos;\n" +
|
||||
" varColor.rgba = vec4(lum, lum, lum, 1.0);\n" +
|
||||
" varTex0.xy = ATTRIB_position;\n" +
|
||||
" varTex0.y = 1.0 - varTex0.y;\n" +
|
||||
" varTex0.zw = vec2(0.0, 0.0);\n" +
|
||||
"}\n");
|
||||
sb.setShader(t);
|
||||
sb.addConstant(mUniformAlloc.getType());
|
||||
sb.addInput(mMesh.getVertexType(0).getElement());
|
||||
mPVCurve = sb.create();
|
||||
mPVCurve.setName("PVCurve");
|
||||
mPVCurve.bindAllocation(mPVA);
|
||||
mPVCurve.bindConstants(mUniformAlloc, 1);
|
||||
|
||||
mRS.contextBindProgramVertex(mPV);
|
||||
}
|
||||
@@ -934,7 +1022,7 @@ public class AllAppsView extends RSSurfaceView
|
||||
private void initProgramFragment() {
|
||||
Sampler.Builder sb = new Sampler.Builder(mRS);
|
||||
sb.setMin(Sampler.Value.LINEAR_MIP_LINEAR);
|
||||
sb.setMag(Sampler.Value.LINEAR);
|
||||
sb.setMag(Sampler.Value.NEAREST);
|
||||
sb.setWrapS(Sampler.Value.CLAMP);
|
||||
sb.setWrapT(Sampler.Value.CLAMP);
|
||||
Sampler linear = sb.create();
|
||||
@@ -944,9 +1032,6 @@ public class AllAppsView extends RSSurfaceView
|
||||
Sampler nearest = sb.create();
|
||||
|
||||
ProgramFragment.Builder bf = new ProgramFragment.Builder(mRS);
|
||||
mPFColor = bf.create();
|
||||
mPFColor.setName("PFColor");
|
||||
|
||||
bf.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
|
||||
ProgramFragment.Builder.Format.RGBA, 0);
|
||||
mPFTexMip = bf.create();
|
||||
@@ -956,6 +1041,13 @@ public class AllAppsView extends RSSurfaceView
|
||||
mPFTexNearest = bf.create();
|
||||
mPFTexNearest.setName("PFTexNearest");
|
||||
mPFTexNearest.bindSampler(nearest, 0);
|
||||
|
||||
bf.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
|
||||
ProgramFragment.Builder.Format.ALPHA, 0);
|
||||
mPFTexMipAlpha = bf.create();
|
||||
mPFTexMipAlpha.setName("PFTexMipAlpha");
|
||||
mPFTexMipAlpha.bindSampler(linear, 0);
|
||||
|
||||
}
|
||||
|
||||
private void initProgramStore() {
|
||||
@@ -967,10 +1059,6 @@ public class AllAppsView extends RSSurfaceView
|
||||
ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
|
||||
mPSIcons = bs.create();
|
||||
mPSIcons.setName("PSIcons");
|
||||
|
||||
//bs.setDitherEnable(false);
|
||||
//mPSText = bs.create();
|
||||
//mPSText.setName("PSText");
|
||||
}
|
||||
|
||||
private void initGl() {
|
||||
@@ -1008,8 +1096,8 @@ public class AllAppsView extends RSSurfaceView
|
||||
mParams.save();
|
||||
mState.save();
|
||||
|
||||
mSelectionBitmap = Bitmap.createBitmap(Defines.ICON_TEXTURE_WIDTH_PX,
|
||||
Defines.ICON_TEXTURE_HEIGHT_PX, Bitmap.Config.ARGB_8888);
|
||||
mSelectionBitmap = Bitmap.createBitmap(Defines.SELECTION_TEXTURE_WIDTH_PX,
|
||||
Defines.SELECTION_TEXTURE_HEIGHT_PX, Bitmap.Config.ARGB_8888);
|
||||
mSelectionCanvas = new Canvas(mSelectionBitmap);
|
||||
|
||||
setApps(null);
|
||||
@@ -1020,11 +1108,12 @@ public class AllAppsView extends RSSurfaceView
|
||||
|
||||
private void initRs() {
|
||||
ScriptC.Builder sb = new ScriptC.Builder(mRS);
|
||||
sb.setScript(mRes, R.raw.rollo3);
|
||||
sb.setScript(mRes, R.raw.allapps);
|
||||
sb.setRoot(true);
|
||||
sb.addDefines(mDefines);
|
||||
sb.setType(mParams.mType, "params", Defines.ALLOC_PARAMS);
|
||||
sb.setType(mState.mType, "state", Defines.ALLOC_STATE);
|
||||
sb.setType(mUniformAlloc.getType(), "vpConstants", Defines.ALLOC_VP_CONSTANTS);
|
||||
mInvokeMove = sb.addInvokable("move");
|
||||
mInvokeFling = sb.addInvokable("fling");
|
||||
mInvokeMoveTo = sb.addInvokable("moveTo");
|
||||
@@ -1035,22 +1124,15 @@ public class AllAppsView extends RSSurfaceView
|
||||
mScript.bindAllocation(mParams.mAlloc, Defines.ALLOC_PARAMS);
|
||||
mScript.bindAllocation(mState.mAlloc, Defines.ALLOC_STATE);
|
||||
mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
|
||||
mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
|
||||
mScript.bindAllocation(mUniformAlloc, Defines.ALLOC_VP_CONSTANTS);
|
||||
|
||||
mRS.contextBindRootScript(mScript);
|
||||
}
|
||||
|
||||
void dirtyCheck() {
|
||||
if (mHasSurface) {
|
||||
if (mAppsDirty && mAllAppsList != null) {
|
||||
for (int i=0; i < mState.iconCount; i++) {
|
||||
uploadAppIcon(i, mAllAppsList.get(i));
|
||||
}
|
||||
saveAppsList();
|
||||
mAppsDirty = false;
|
||||
}
|
||||
if (mZoomDirty) {
|
||||
setZoom(mZoom, mAnimateNextZoom);
|
||||
}
|
||||
if (mZoomDirty) {
|
||||
setZoom(mNextZoom, mAnimateNextZoom);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1065,21 +1147,18 @@ public class AllAppsView extends RSSurfaceView
|
||||
mIconIds = new int[allocCount];
|
||||
mAllocIconIds = Allocation.createSized(mRS, Element.USER_I32(mRS), allocCount);
|
||||
|
||||
mLabels = new Allocation[count];
|
||||
mLabelIds = new int[allocCount];
|
||||
mAllocLabelIds = Allocation.createSized(mRS, Element.USER_I32(mRS), allocCount);
|
||||
|
||||
Element ie8888 = Element.RGBA_8888(mRS);
|
||||
|
||||
mState.iconCount = count;
|
||||
long before = SystemClock.uptimeMillis();
|
||||
for (int i=0; i < mState.iconCount; i++) {
|
||||
createAppIconAllocations(i, list.get(i));
|
||||
}
|
||||
long after = SystemClock.uptimeMillis();
|
||||
//Log.d(TAG, "createAppIconAllocations took " + (after-before) + "ms");
|
||||
if (mHasSurface) {
|
||||
for (int i=0; i < mState.iconCount; i++) {
|
||||
uploadAppIcon(i, list.get(i));
|
||||
}
|
||||
} else {
|
||||
mRollo.mAppsDirty = true;
|
||||
for (int i=0; i < mState.iconCount; i++) {
|
||||
uploadAppIcon(i, list.get(i));
|
||||
}
|
||||
saveAppsList();
|
||||
}
|
||||
@@ -1098,29 +1177,13 @@ public class AllAppsView extends RSSurfaceView
|
||||
}
|
||||
}
|
||||
|
||||
private void frameBitmapAllocMips(Allocation alloc, int w, int h) {
|
||||
int black[] = new int[w > h ? w : h];
|
||||
Allocation.Adapter2D a = alloc.createAdapter2D();
|
||||
int mip = 0;
|
||||
while (w > 1 || h > 1) {
|
||||
a.subData(0, 0, 1, h, black);
|
||||
a.subData(w-1, 0, 1, h, black);
|
||||
a.subData(0, 0, w, 1, black);
|
||||
a.subData(0, h-1, w, 1, black);
|
||||
mip++;
|
||||
w = (w + 1) >> 1;
|
||||
h = (h + 1) >> 1;
|
||||
a.setConstraint(Dimension.LOD, mip);
|
||||
}
|
||||
a.subData(0, 0, 1, 1, black);
|
||||
}
|
||||
|
||||
private void createAppIconAllocations(int index, ApplicationInfo item) {
|
||||
Bitmap bitmap = item.iconBitmap;
|
||||
mIcons[index] = Allocation.createFromBitmap(mRS, bitmap, Element.RGBA_8888(mRS), true);
|
||||
frameBitmapAllocMips(mIcons[index], bitmap.getWidth(), bitmap.getHeight());
|
||||
|
||||
mIcons[index] = Allocation.createFromBitmap(mRS, item.iconBitmap,
|
||||
Element.RGBA_8888(mRS), true);
|
||||
mLabels[index] = Allocation.createFromBitmap(mRS, item.titleBitmap,
|
||||
Element.A_8(mRS), true);
|
||||
mIconIds[index] = mIcons[index].getID();
|
||||
mLabelIds[index] = mLabels[index].getID();
|
||||
}
|
||||
|
||||
private void uploadAppIcon(int index, ApplicationInfo item) {
|
||||
@@ -1131,6 +1194,7 @@ public class AllAppsView extends RSSurfaceView
|
||||
+ " item=" + item);
|
||||
}
|
||||
mIcons[index].uploadToTexture(0);
|
||||
mLabels[index].uploadToTexture(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1142,13 +1206,21 @@ public class AllAppsView extends RSSurfaceView
|
||||
int[] iconIds = new int[count];
|
||||
mAllocIconIds = Allocation.createSized(mRS, Element.USER_I32(mRS), count);
|
||||
|
||||
Allocation[] labels = new Allocation[count];
|
||||
int[] labelIds = new int[count];
|
||||
mAllocLabelIds = Allocation.createSized(mRS, Element.USER_I32(mRS), count);
|
||||
|
||||
final int oldCount = mRollo.mState.iconCount;
|
||||
|
||||
System.arraycopy(mIcons, 0, icons, 0, oldCount);
|
||||
System.arraycopy(mIconIds, 0, iconIds, 0, oldCount);
|
||||
System.arraycopy(mLabels, 0, labels, 0, oldCount);
|
||||
System.arraycopy(mLabelIds, 0, labelIds, 0, oldCount);
|
||||
|
||||
mIcons = icons;
|
||||
mIconIds = iconIds;
|
||||
mLabels = labels;
|
||||
mLabelIds = labelIds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1160,15 +1232,11 @@ public class AllAppsView extends RSSurfaceView
|
||||
|
||||
System.arraycopy(mIcons, index, mIcons, dest, count);
|
||||
System.arraycopy(mIconIds, index, mIconIds, dest, count);
|
||||
System.arraycopy(mLabels, index, mLabels, dest, count);
|
||||
System.arraycopy(mLabelIds, index, mLabelIds, dest, count);
|
||||
|
||||
createAppIconAllocations(index, item);
|
||||
|
||||
if (mHasSurface) {
|
||||
uploadAppIcon(index, item);
|
||||
} else {
|
||||
mAppsDirty = true;
|
||||
}
|
||||
|
||||
uploadAppIcon(index, item);
|
||||
mRollo.mState.iconCount++;
|
||||
}
|
||||
|
||||
@@ -1181,12 +1249,16 @@ public class AllAppsView extends RSSurfaceView
|
||||
|
||||
System.arraycopy(mIcons, src, mIcons, index, count);
|
||||
System.arraycopy(mIconIds, src, mIconIds, index, count);
|
||||
System.arraycopy(mLabels, src, mLabels, index, count);
|
||||
System.arraycopy(mLabelIds, src, mLabelIds, index, count);
|
||||
|
||||
mRollo.mState.iconCount--;
|
||||
final int last = mState.iconCount;
|
||||
|
||||
mIcons[last] = null;
|
||||
mIconIds[last] = 0;
|
||||
mLabels[last] = null;
|
||||
mLabelIds[last] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1196,9 +1268,11 @@ public class AllAppsView extends RSSurfaceView
|
||||
mRS.contextBindRootScript(null);
|
||||
|
||||
mAllocIconIds.data(mIconIds);
|
||||
mAllocLabelIds.data(mLabelIds);
|
||||
|
||||
if (mScript != null) { // this happens when we init it
|
||||
mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
|
||||
mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
|
||||
}
|
||||
|
||||
mState.save();
|
||||
@@ -1208,7 +1282,9 @@ public class AllAppsView extends RSSurfaceView
|
||||
if (mInvokeResetWAR != null) {
|
||||
mInvokeResetWAR.execute();
|
||||
}
|
||||
mRS.contextBindRootScript(mScript);
|
||||
if (mScript != null) {
|
||||
mRS.contextBindRootScript(mScript);
|
||||
}
|
||||
}
|
||||
|
||||
void initTouchState() {
|
||||
@@ -1313,7 +1389,7 @@ public class AllAppsView extends RSSurfaceView
|
||||
ApplicationInfo info = mAllAppsList.get(index);
|
||||
Bitmap selectionBitmap = mSelectionBitmap;
|
||||
|
||||
Utilities.drawSelectedAllAppsBitmap(mSelectionCanvas, selectionBitmap,
|
||||
Utilities.drawSelectedAllAppsBitmap(mSelectionCanvas,
|
||||
selectionBitmap.getWidth(), selectionBitmap.getHeight(),
|
||||
pressed == SELECTED_PRESSED, info.iconBitmap);
|
||||
|
||||
@@ -1368,10 +1444,12 @@ public class AllAppsView extends RSSurfaceView
|
||||
Log.d(TAG, "mRollo.mIconIds.length=" + mIconIds.length);
|
||||
}
|
||||
Log.d(TAG, "mRollo.mIconIds=" + Arrays.toString(mIconIds));
|
||||
if (mLabelIds != null) {
|
||||
Log.d(TAG, "mRollo.mLabelIds.length=" + mLabelIds.length);
|
||||
}
|
||||
Log.d(TAG, "mRollo.mLabelIds=" + Arrays.toString(mLabelIds));
|
||||
Log.d(TAG, "mRollo.mTouchXBorders=" + Arrays.toString(mTouchXBorders));
|
||||
Log.d(TAG, "mRollo.mTouchYBorders=" + Arrays.toString(mTouchYBorders));
|
||||
Log.d(TAG, "mRollo.mHasSurface=" + mHasSurface);
|
||||
Log.d(TAG, "mRollo.mAppsDirty=" + mAppsDirty);
|
||||
Log.d(TAG, "mRollo.mState.newPositionX=" + mState.newPositionX);
|
||||
Log.d(TAG, "mRollo.mState.newTouchDown=" + mState.newTouchDown);
|
||||
Log.d(TAG, "mRollo.mState.flingVelocity=" + mState.flingVelocity);
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.os.Process;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Cache of application icons. Icons can be made from any thread.
|
||||
*/
|
||||
public class AppInfoCache {
|
||||
private static final String TAG = "Launcher.AppInfoCache";
|
||||
|
||||
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
|
||||
|
||||
private static final HashMap<ComponentName, ApplicationInfo> sCache =
|
||||
new HashMap<ComponentName, ApplicationInfo>(INITIAL_ICON_CACHE_CAPACITY);
|
||||
|
||||
/**
|
||||
* no public constructor.
|
||||
*/
|
||||
private AppInfoCache() {
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given ResolveInfo, return an ApplicationInfo and cache the result for later.
|
||||
*/
|
||||
public static ApplicationInfo cache(ResolveInfo info, Context context,
|
||||
Utilities.BubbleText bubble) {
|
||||
synchronized (sCache) {
|
||||
ComponentName componentName = new ComponentName(
|
||||
info.activityInfo.applicationInfo.packageName,
|
||||
info.activityInfo.name);
|
||||
ApplicationInfo application = sCache.get(componentName);
|
||||
|
||||
if (application == null) {
|
||||
application = new ApplicationInfo();
|
||||
application.container = ItemInfo.NO_ID;
|
||||
|
||||
updateTitleAndIcon(info, application, context, bubble);
|
||||
|
||||
application.setActivity(componentName,
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
||||
|
||||
sCache.put(componentName, application);
|
||||
}
|
||||
|
||||
return application;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the entry in the in the cache with its new metadata.
|
||||
*/
|
||||
public static void update(ResolveInfo info, ApplicationInfo applicationInfo, Context context,
|
||||
Utilities.BubbleText bubble) {
|
||||
synchronized (sCache) {
|
||||
updateTitleAndIcon(info, applicationInfo, context, bubble);
|
||||
|
||||
ComponentName componentName = new ComponentName(
|
||||
info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
|
||||
sCache.put(componentName, applicationInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any records for the supplied ComponentName.
|
||||
*/
|
||||
public static void remove(ComponentName componentName) {
|
||||
synchronized (sCache) {
|
||||
sCache.remove(componentName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty out the cache.
|
||||
*/
|
||||
public static void flush() {
|
||||
synchronized (sCache) {
|
||||
sCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon for the supplied ApplicationInfo. If that activity already
|
||||
* exists in the cache, use that.
|
||||
*/
|
||||
public static Drawable getIconDrawable(PackageManager packageManager, ApplicationInfo info) {
|
||||
final ResolveInfo resolveInfo = packageManager.resolveActivity(info.intent, 0);
|
||||
if (resolveInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ComponentName componentName = new ComponentName(
|
||||
resolveInfo.activityInfo.applicationInfo.packageName,
|
||||
resolveInfo.activityInfo.name);
|
||||
ApplicationInfo cached;
|
||||
synchronized (sCache) {
|
||||
cached = sCache.get(componentName);
|
||||
if (cached != null) {
|
||||
if (cached.icon == null) {
|
||||
cached.icon = resolveInfo.activityInfo.loadIcon(packageManager);
|
||||
}
|
||||
return cached.icon;
|
||||
} else {
|
||||
return resolveInfo.activityInfo.loadIcon(packageManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the cache and disconnect any of the callbacks in the drawables or we
|
||||
* leak the previous Home screen on orientation change.
|
||||
*/
|
||||
public static void unbindDrawables() {
|
||||
synchronized (sCache) {
|
||||
for (ApplicationInfo appInfo: sCache.values()) {
|
||||
if (appInfo.icon != null) {
|
||||
appInfo.icon.setCallback(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the title and icon. Don't keep a reference to the context!
|
||||
*/
|
||||
private static void updateTitleAndIcon(ResolveInfo info, ApplicationInfo application,
|
||||
Context context, Utilities.BubbleText bubble) {
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
|
||||
application.title = info.loadLabel(packageManager);
|
||||
if (application.title == null) {
|
||||
application.title = info.activityInfo.name;
|
||||
}
|
||||
|
||||
// TODO: turn this on in froyo, not enough time for testing in mr3
|
||||
//if (application.iconBitmap != null) {
|
||||
// application.iconBitmap.recycle();
|
||||
//}
|
||||
application.iconBitmap = Utilities.createAllAppsBitmap(
|
||||
info.activityInfo.loadIcon(packageManager),
|
||||
application.title.toString(), bubble, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -36,54 +37,48 @@ 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.
|
||||
*/
|
||||
Intent intent;
|
||||
|
||||
/**
|
||||
* The application icon.
|
||||
*/
|
||||
Drawable icon;
|
||||
|
||||
/**
|
||||
* What we show in all apps, including the text.
|
||||
* A bitmap version of the application icon.
|
||||
*/
|
||||
Bitmap iconBitmap;
|
||||
|
||||
/**
|
||||
* When set to true, indicates that the icon has been resized.
|
||||
*/
|
||||
boolean filtered;
|
||||
ComponentName componentName;
|
||||
|
||||
/**
|
||||
* Indicates whether the icon comes from an application's resource (if false)
|
||||
* or from a custom Bitmap (if true.)
|
||||
*/
|
||||
boolean customIcon;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,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 + "\" icon=" + info.icon
|
||||
+ " iconBitmap=" + info.iconBitmap + " filtered=" + info.filtered
|
||||
+ " customIcon=" + info.customIcon);
|
||||
Log.d(tag, " title=\"" + info.title + "\" titleBitmap=" + info.titleBitmap
|
||||
+ " iconBitmap=" + info.iconBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
public ShortcutInfo makeShortcut() {
|
||||
return new ShortcutInfo(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,8 +565,11 @@ public class CellLayout extends ViewGroup {
|
||||
if (lp.dropped) {
|
||||
lp.dropped = false;
|
||||
|
||||
final int[] cellXY = mCellXY;
|
||||
getLocationOnScreen(cellXY);
|
||||
mWallpaperManager.sendWallpaperCommand(getWindowToken(), "android.home.drop",
|
||||
childLeft + lp.width / 2, childTop + lp.height / 2, 0, null);
|
||||
cellXY[0] + childLeft + lp.width / 2,
|
||||
cellXY[1] + childTop + lp.height / 2, 0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -18,25 +18,18 @@ package com.android.launcher2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.IBinder;
|
||||
import android.os.Handler;
|
||||
import android.os.Vibrator;
|
||||
import android.os.SystemClock;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -44,6 +37,7 @@ import java.util.ArrayList;
|
||||
* Class for initiating a drag within a view or across multiple views.
|
||||
*/
|
||||
public class DragController {
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
private static final String TAG = "Launcher.DragController";
|
||||
|
||||
/** Indicates the drag is a move. */
|
||||
@@ -113,6 +107,8 @@ public class DragController {
|
||||
/** The view that will be scrolled when dragging to the left and right edges of the screen. */
|
||||
private View mScrollView;
|
||||
|
||||
private View mMoveTarget;
|
||||
|
||||
private DragScroller mDragScroller;
|
||||
private int mScrollState = SCROLL_OUTSIDE_ZONE;
|
||||
private ScrollRunnable mScrollRunnable = new ScrollRunnable();
|
||||
@@ -147,7 +143,6 @@ public class DragController {
|
||||
* Used to create a new DragLayer from XML.
|
||||
*
|
||||
* @param context The application's context.
|
||||
* @param attrs The attribtues set containing the Workspace's customization values.
|
||||
*/
|
||||
public DragController(Context context) {
|
||||
mContext = context;
|
||||
@@ -159,7 +154,7 @@ public class DragController {
|
||||
*
|
||||
* @param v The view that is being dragged
|
||||
* @param source An object representing where the drag originated
|
||||
* @param info The data associated with the object that is being dragged
|
||||
* @param dragInfo The data associated with the object that is being dragged
|
||||
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
||||
* {@link #DRAG_ACTION_COPY}
|
||||
*/
|
||||
@@ -195,7 +190,7 @@ public class DragController {
|
||||
* @param textureWidth The width of the region inside b to use.
|
||||
* @param textureHeight The height of the region inside b to use.
|
||||
* @param source An object representing where the drag originated
|
||||
* @param info The data associated with the object that is being dragged
|
||||
* @param dragInfo The data associated with the object that is being dragged
|
||||
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
|
||||
* {@link #DRAG_ACTION_COPY}
|
||||
*/
|
||||
@@ -275,6 +270,7 @@ public class DragController {
|
||||
* || super.dispatchKeyEvent(event);
|
||||
* </pre>
|
||||
*/
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
return mDragging;
|
||||
}
|
||||
@@ -342,6 +338,17 @@ public class DragController {
|
||||
return mDragging;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the view that should handle move events.
|
||||
*/
|
||||
void setMoveTarget(View view) {
|
||||
mMoveTarget = view;
|
||||
}
|
||||
|
||||
public boolean dispatchUnhandledMove(View focused, int direction) {
|
||||
return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this from a drag source view.
|
||||
*/
|
||||
@@ -377,7 +384,7 @@ public class DragController {
|
||||
|
||||
// Drop on someone?
|
||||
final int[] coordinates = mCoordinatesTemp;
|
||||
DropTarget dropTarget = findDropTarget((int) screenX, (int) screenY, coordinates);
|
||||
DropTarget dropTarget = findDropTarget(screenX, screenY, coordinates);
|
||||
if (dropTarget != null) {
|
||||
if (mLastDropTarget == dropTarget) {
|
||||
dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],
|
||||
|
||||
@@ -18,9 +18,9 @@ package com.android.launcher2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
@@ -57,4 +57,9 @@ public class DragLayer extends FrameLayout {
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
return mDragController.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchUnhandledMove(View focused, int direction) {
|
||||
return mDragController.dispatchUnhandledMove(focused, direction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import android.view.WindowManagerImpl;
|
||||
|
||||
public class DragView extends View implements TweenCallback {
|
||||
// Number of pixels to add to the dragged item for scaling. Should be even for pixel alignment.
|
||||
private static final int DRAG_SCALE = 24;
|
||||
private static final int DRAG_SCALE = 40;
|
||||
|
||||
private Bitmap mBitmap;
|
||||
private Paint mPaint;
|
||||
|
||||
@@ -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,140 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.os.Process;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Cache of application icons. Icons can be made from any thread.
|
||||
*/
|
||||
public class IconCache {
|
||||
private static final String TAG = "Launcher.IconCache";
|
||||
|
||||
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
|
||||
|
||||
private static class CacheEntry {
|
||||
public Bitmap icon;
|
||||
public String title;
|
||||
public Bitmap titleBitmap;
|
||||
}
|
||||
|
||||
private LauncherApplication mContext;
|
||||
private PackageManager mPackageManager;
|
||||
private Utilities.BubbleText mBubble;
|
||||
private final HashMap<ComponentName, CacheEntry> mCache =
|
||||
new HashMap<ComponentName, CacheEntry>(INITIAL_ICON_CACHE_CAPACITY);
|
||||
|
||||
public IconCache(LauncherApplication context) {
|
||||
mContext = context;
|
||||
mPackageManager = context.getPackageManager();
|
||||
mBubble = new Utilities.BubbleText(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any records for the supplied ComponentName.
|
||||
*/
|
||||
public void remove(ComponentName componentName) {
|
||||
synchronized (mCache) {
|
||||
mCache.remove(componentName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty out the cache.
|
||||
*/
|
||||
public void flush() {
|
||||
synchronized (mCache) {
|
||||
mCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in "application" with the icon and label for "info."
|
||||
*/
|
||||
public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info) {
|
||||
synchronized (mCache) {
|
||||
CacheEntry entry = cacheLocked(application.componentName, info);
|
||||
if (entry.titleBitmap == null) {
|
||||
entry.titleBitmap = mBubble.createTextBitmap(entry.title.toString());
|
||||
}
|
||||
|
||||
application.title = entry.title;
|
||||
application.titleBitmap = entry.titleBitmap;
|
||||
application.iconBitmap = entry.icon;
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap getIcon(Intent intent) {
|
||||
final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
|
||||
ComponentName component = intent.getComponent();
|
||||
|
||||
if (resolveInfo == null || component == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CacheEntry entry = cacheLocked(component, resolveInfo);
|
||||
return entry.icon;
|
||||
}
|
||||
|
||||
public Bitmap getIcon(ComponentName component, ResolveInfo resolveInfo) {
|
||||
if (resolveInfo == null || component == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CacheEntry entry = cacheLocked(component, resolveInfo);
|
||||
return entry.icon;
|
||||
}
|
||||
|
||||
private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
|
||||
CacheEntry entry = mCache.get(componentName);
|
||||
if (entry == null) {
|
||||
entry = new CacheEntry();
|
||||
|
||||
mCache.put(componentName, entry);
|
||||
|
||||
entry.title = info.loadLabel(mPackageManager).toString();
|
||||
if (entry.title == null) {
|
||||
entry.title = info.activityInfo.name;
|
||||
}
|
||||
entry.icon = Utilities.createIconBitmap(
|
||||
info.activityInfo.loadIcon(mPackageManager), mContext);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.launcher2;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.ISearchManager;
|
||||
import android.app.SearchManager;
|
||||
import android.app.StatusBarManager;
|
||||
import android.app.WallpaperManager;
|
||||
@@ -43,16 +42,11 @@ import android.graphics.Rect;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.LiveFolders;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.text.Selection;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
@@ -67,6 +61,7 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
@@ -99,6 +94,8 @@ public final class Launcher extends Activity
|
||||
private static final int WALLPAPER_SCREENS_SPAN = 2;
|
||||
|
||||
private static final int MENU_GROUP_ADD = 1;
|
||||
private static final int MENU_GROUP_WALLPAPER = MENU_GROUP_ADD + 1;
|
||||
|
||||
private static final int MENU_ADD = Menu.FIRST + 1;
|
||||
private static final int MENU_WALLPAPER_SETTINGS = MENU_ADD + 1;
|
||||
private static final int MENU_SEARCH = MENU_WALLPAPER_SETTINGS + 1;
|
||||
@@ -197,6 +194,7 @@ public final class Launcher extends Activity
|
||||
private Bundle mSavedInstanceState;
|
||||
|
||||
private LauncherModel mModel;
|
||||
private IconCache mIconCache;
|
||||
|
||||
private ArrayList<ItemInfo> mDesktopItems = new ArrayList<ItemInfo>();
|
||||
private static HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
|
||||
@@ -204,13 +202,13 @@ public final class Launcher extends Activity
|
||||
private ImageView mPreviousView;
|
||||
private ImageView mNextView;
|
||||
|
||||
private boolean mUtsTestMode;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mModel = ((LauncherApplication)getApplication()).setLauncher(this);
|
||||
LauncherApplication app = ((LauncherApplication)getApplication());
|
||||
mModel = app.setLauncher(this);
|
||||
mIconCache = app.getIconCache();
|
||||
mDragController = new DragController(this);
|
||||
mInflater = getLayoutInflater();
|
||||
|
||||
@@ -279,7 +277,7 @@ public final class Launcher extends Activity
|
||||
localeConfiguration.mnc = mnc;
|
||||
|
||||
writeConfiguration(this, localeConfiguration);
|
||||
AppInfoCache.flush();
|
||||
mIconCache.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,7 +409,6 @@ public final class Launcher extends Activity
|
||||
super.onResume();
|
||||
|
||||
mPaused = false;
|
||||
mUtsTestMode = SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1;
|
||||
|
||||
if (mRestoring) {
|
||||
mWorkspaceLoading = true;
|
||||
@@ -454,6 +451,27 @@ public final class Launcher extends Activity
|
||||
return null;
|
||||
}
|
||||
|
||||
// We can't hide the IME if it was forced open. So don't bother
|
||||
/*
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
if (hasFocus) {
|
||||
final InputMethodManager inputManager = (InputMethodManager)
|
||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
WindowManager.LayoutParams lp = getWindow().getAttributes();
|
||||
inputManager.hideSoftInputFromWindow(lp.token, 0, new android.os.ResultReceiver(new
|
||||
android.os.Handler()) {
|
||||
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||
Log.d(TAG, "ResultReceiver got resultCode=" + resultCode);
|
||||
}
|
||||
});
|
||||
Log.d(TAG, "called hideSoftInputFromWindow from onWindowFocusChanged");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private boolean acceptFilter() {
|
||||
final InputMethodManager inputManager = (InputMethodManager)
|
||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
@@ -462,10 +480,6 @@ public final class Launcher extends Activity
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (mUtsTestMode) {
|
||||
return handleUtsTestModeKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
boolean handled = super.onKeyDown(keyCode, event);
|
||||
if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
|
||||
boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
|
||||
@@ -481,50 +495,9 @@ public final class Launcher extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
public boolean handleUtsTestModeKeyDown(int keyCode, KeyEvent event) {
|
||||
Log.d(TAG, "UTS-TEST-MODE");
|
||||
boolean handled = super.onKeyDown(keyCode, event);
|
||||
if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
|
||||
boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
|
||||
keyCode, event);
|
||||
if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
|
||||
// something usable has been typed - dispatch it now.
|
||||
final String str = mDefaultKeySsb.toString();
|
||||
|
||||
boolean isDialable = true;
|
||||
final int count = str.length();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!PhoneNumberUtils.isReallyDialable(str.charAt(i))) {
|
||||
isDialable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Intent intent;
|
||||
if (isDialable) {
|
||||
intent = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", str, null));
|
||||
} else {
|
||||
intent = new Intent(ContactsContract.Intents.UI.FILTER_CONTACTS_ACTION);
|
||||
intent.putExtra(ContactsContract.Intents.UI.FILTER_TEXT_EXTRA_KEY, str);
|
||||
}
|
||||
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
||||
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException ex) {
|
||||
// Oh well... no one knows how to filter/dial. Life goes on.
|
||||
}
|
||||
|
||||
mDefaultKeySsb.clear();
|
||||
mDefaultKeySsb.clearSpans();
|
||||
Selection.setSelection(mDefaultKeySsb, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Eat the long press event so the keyboard doesn't come up.
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && event.isLongPress()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return handled;
|
||||
@@ -603,6 +576,7 @@ public final class Launcher extends Activity
|
||||
|
||||
mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
|
||||
final Workspace workspace = mWorkspace;
|
||||
workspace.setHapticFeedbackEnabled(false);
|
||||
|
||||
DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
|
||||
mDeleteZone = deleteZone;
|
||||
@@ -610,6 +584,7 @@ public final class Launcher extends Activity
|
||||
mHandleView = (HandleView) findViewById(R.id.all_apps_button);
|
||||
mHandleView.setLauncher(this);
|
||||
mHandleView.setOnClickListener(this);
|
||||
mHandleView.setOnLongClickListener(this);
|
||||
|
||||
mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
|
||||
mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
|
||||
@@ -634,6 +609,7 @@ public final class Launcher extends Activity
|
||||
dragController.setDragScoller(workspace);
|
||||
dragController.setDragListener(deleteZone);
|
||||
dragController.setScrollView(dragLayer);
|
||||
dragController.setMoveTarget(workspace);
|
||||
|
||||
// The order here is bottom to top.
|
||||
dragController.addDropTarget(workspace);
|
||||
@@ -661,7 +637,7 @@ public final class Launcher extends Activity
|
||||
*
|
||||
* @return A View inflated from R.layout.application.
|
||||
*/
|
||||
View createShortcut(ApplicationInfo info) {
|
||||
View createShortcut(ShortcutInfo info) {
|
||||
return createShortcut(R.layout.application,
|
||||
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info);
|
||||
}
|
||||
@@ -675,18 +651,12 @@ public final class Launcher extends Activity
|
||||
*
|
||||
* @return A View inflated from layoutResId.
|
||||
*/
|
||||
View createShortcut(int layoutResId, ViewGroup parent, ApplicationInfo info) {
|
||||
View createShortcut(int layoutResId, ViewGroup parent, ShortcutInfo info) {
|
||||
TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
|
||||
|
||||
if (info.icon == null) {
|
||||
info.icon = AppInfoCache.getIconDrawable(getPackageManager(), info);
|
||||
}
|
||||
if (!info.filtered) {
|
||||
info.icon = Utilities.createIconThumbnail(info.icon, this);
|
||||
info.filtered = true;
|
||||
}
|
||||
|
||||
favorite.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
|
||||
favorite.setCompoundDrawablesWithIntrinsicBounds(null,
|
||||
new FastBitmapDrawable(info.getIcon(mIconCache)),
|
||||
null, null);
|
||||
favorite.setText(info.title);
|
||||
favorite.setTag(info);
|
||||
favorite.setOnClickListener(this);
|
||||
@@ -704,39 +674,17 @@ public final class Launcher extends Activity
|
||||
cellInfo.screen = mWorkspace.getCurrentScreen();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
|
||||
final ApplicationInfo info = infoFromApplicationIntent(context, data);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -749,7 +697,7 @@ public final class Launcher extends Activity
|
||||
cellInfo.screen = mWorkspace.getCurrentScreen();
|
||||
if (!findSingleSlot(cellInfo)) return;
|
||||
|
||||
final ApplicationInfo info = addShortcut(this, data, cellInfo, false);
|
||||
final ShortcutInfo info = mModel.addShortcut(this, data, cellInfo, false);
|
||||
|
||||
if (!mRestoring) {
|
||||
final View view = createShortcut(info);
|
||||
@@ -816,61 +764,6 @@ public final class Launcher extends Activity
|
||||
return mAppWidgetHost;
|
||||
}
|
||||
|
||||
static ApplicationInfo addShortcut(Context context, Intent data,
|
||||
CellLayout.CellInfo cellInfo, boolean notify) {
|
||||
|
||||
final ApplicationInfo info = infoFromShortcutIntent(context, data);
|
||||
LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private static ApplicationInfo infoFromShortcutIntent(Context context, Intent data) {
|
||||
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
|
||||
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
Bitmap bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
|
||||
|
||||
Drawable icon = null;
|
||||
boolean filtered = false;
|
||||
boolean customIcon = false;
|
||||
ShortcutIconResource iconResource = null;
|
||||
|
||||
if (bitmap != null) {
|
||||
icon = new FastBitmapDrawable(Utilities.createBitmapThumbnail(bitmap, context));
|
||||
filtered = true;
|
||||
customIcon = true;
|
||||
} else {
|
||||
Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
|
||||
if (extra != null && extra instanceof ShortcutIconResource) {
|
||||
try {
|
||||
iconResource = (ShortcutIconResource) extra;
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
Resources resources = packageManager.getResourcesForApplication(
|
||||
iconResource.packageName);
|
||||
final int id = resources.getIdentifier(iconResource.resourceName, null, null);
|
||||
icon = resources.getDrawable(id);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Could not load shortcut icon: " + extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
icon = context.getPackageManager().getDefaultActivityIcon();
|
||||
}
|
||||
|
||||
final ApplicationInfo info = new ApplicationInfo();
|
||||
info.icon = icon;
|
||||
info.filtered = filtered;
|
||||
info.title = name;
|
||||
info.intent = intent;
|
||||
info.customIcon = customIcon;
|
||||
info.iconResource = iconResource;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void closeSystemDialogs() {
|
||||
getWindow().closeAllPanels();
|
||||
|
||||
@@ -987,7 +880,6 @@ public final class Launcher extends Activity
|
||||
mModel.stopLoader();
|
||||
|
||||
unbindDesktopItems();
|
||||
AppInfoCache.unbindDrawables();
|
||||
|
||||
getContentResolver().unregisterContentObserver(mWidgetObserver);
|
||||
|
||||
@@ -1079,10 +971,11 @@ public final class Launcher extends Activity
|
||||
}
|
||||
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
menu.add(MENU_GROUP_ADD, MENU_ADD, 0, R.string.menu_add)
|
||||
.setIcon(android.R.drawable.ic_menu_add)
|
||||
.setAlphabeticShortcut('A');
|
||||
menu.add(0, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)
|
||||
menu.add(MENU_GROUP_WALLPAPER, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)
|
||||
.setIcon(android.R.drawable.ic_menu_gallery)
|
||||
.setAlphabeticShortcut('W');
|
||||
menu.add(0, MENU_SEARCH, 0, R.string.menu_search)
|
||||
@@ -1107,8 +1000,22 @@ public final class Launcher extends Activity
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
||||
mMenuAddInfo = mWorkspace.findAllVacantCells(null);
|
||||
menu.setGroupEnabled(MENU_GROUP_ADD, mMenuAddInfo != null && mMenuAddInfo.valid);
|
||||
// If all apps is animating, don't show the menu, because we don't know
|
||||
// which one to show.
|
||||
if (mAllAppsGrid.isVisible() && !mAllAppsGrid.isOpaque()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only show the add and wallpaper options when we're not in all apps.
|
||||
boolean visible = !mAllAppsGrid.isOpaque();
|
||||
menu.setGroupVisible(MENU_GROUP_ADD, visible);
|
||||
menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
|
||||
|
||||
// Disable add if the workspace is full.
|
||||
if (visible) {
|
||||
mMenuAddInfo = mWorkspace.findAllVacantCells(null);
|
||||
menu.setGroupEnabled(MENU_GROUP_ADD, mMenuAddInfo != null && mMenuAddInfo.valid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1276,7 +1183,6 @@ public final class Launcher extends Activity
|
||||
String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
|
||||
|
||||
Drawable icon = null;
|
||||
boolean filtered = false;
|
||||
Intent.ShortcutIconResource iconResource = null;
|
||||
|
||||
Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
|
||||
@@ -1298,8 +1204,7 @@ public final class Launcher extends Activity
|
||||
}
|
||||
|
||||
final LiveFolderInfo info = new LiveFolderInfo();
|
||||
info.icon = icon;
|
||||
info.filtered = filtered;
|
||||
info.icon = Utilities.createIconBitmap(icon, context);
|
||||
info.title = name;
|
||||
info.iconResource = iconResource;
|
||||
info.uri = data.getData();
|
||||
@@ -1451,9 +1356,9 @@ public final class Launcher extends Activity
|
||||
*/
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag instanceof ApplicationInfo) {
|
||||
if (tag instanceof ShortcutInfo) {
|
||||
// Open shortcut
|
||||
final Intent intent = ((ApplicationInfo) tag).intent;
|
||||
final Intent intent = ((ShortcutInfo)tag).intent;
|
||||
int[] pos = new int[2];
|
||||
v.getLocationOnScreen(pos);
|
||||
intent.setSourceBounds(
|
||||
@@ -1542,14 +1447,21 @@ public final class Launcher extends Activity
|
||||
if (!isAllAppsVisible()) {
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
showPreviousPreview(v);
|
||||
showPreviews(v);
|
||||
}
|
||||
return true;
|
||||
case R.id.next_screen:
|
||||
if (!isAllAppsVisible()) {
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
showNextPreview(v);
|
||||
showPreviews(v);
|
||||
}
|
||||
return true;
|
||||
case R.id.all_apps_button:
|
||||
if (!isAllAppsVisible()) {
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
showPreviews(v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1574,6 +1486,8 @@ public final class Launcher extends Activity
|
||||
if (cellInfo.valid) {
|
||||
// User long pressed on empty space
|
||||
mWorkspace.setAllowLongPress(false);
|
||||
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
showAddDialog(cellInfo);
|
||||
}
|
||||
} else {
|
||||
@@ -1612,29 +1526,19 @@ public final class Launcher extends Activity
|
||||
v.setTag(null);
|
||||
}
|
||||
|
||||
private void showPreviousPreview(View anchor) {
|
||||
int current = mWorkspace.getCurrentScreen();
|
||||
if (current <= 0) return;
|
||||
|
||||
private void showPreviews(View anchor) {
|
||||
showPreviews(anchor, 0, mWorkspace.getChildCount());
|
||||
}
|
||||
|
||||
private void showNextPreview(View anchor) {
|
||||
int current = mWorkspace.getCurrentScreen();
|
||||
if (current >= mWorkspace.getChildCount() - 1) return;
|
||||
|
||||
showPreviews(anchor, 0, mWorkspace.getChildCount());
|
||||
}
|
||||
|
||||
private void showPreviews(final View anchor, int start, int end) {
|
||||
Resources resources = getResources();
|
||||
final Resources resources = getResources();
|
||||
final Workspace workspace = mWorkspace;
|
||||
|
||||
Workspace workspace = mWorkspace;
|
||||
CellLayout cell = ((CellLayout) workspace.getChildAt(start));
|
||||
|
||||
float max = workspace.getChildCount();
|
||||
|
||||
Rect r = new Rect();
|
||||
final Rect r = new Rect();
|
||||
resources.getDrawable(R.drawable.preview_background).getPadding(r);
|
||||
int extraW = (int) ((r.left + r.right) * max);
|
||||
int extraH = r.top + r.bottom;
|
||||
@@ -1665,10 +1569,10 @@ public final class Launcher extends Activity
|
||||
ImageView image = new ImageView(this);
|
||||
cell = (CellLayout) workspace.getChildAt(i);
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap((int) sWidth, (int) sHeight,
|
||||
final Bitmap bitmap = Bitmap.createBitmap((int) sWidth, (int) sHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas c = new Canvas(bitmap);
|
||||
|
||||
final Canvas c = new Canvas(bitmap);
|
||||
c.scale(scale, scale);
|
||||
c.translate(-cell.getLeftPadding(), -cell.getTopPadding());
|
||||
cell.dispatchDraw(c);
|
||||
@@ -1686,8 +1590,8 @@ public final class Launcher extends Activity
|
||||
|
||||
bitmaps.add(bitmap);
|
||||
}
|
||||
|
||||
PopupWindow p = new PopupWindow(this);
|
||||
|
||||
final PopupWindow p = new PopupWindow(this);
|
||||
p.setContentView(preview);
|
||||
p.setWidth((int) (sWidth * count + extraW));
|
||||
p.setHeight((int) (sHeight + extraH));
|
||||
@@ -1731,10 +1635,6 @@ public final class Launcher extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
View getDrawerHandle() {
|
||||
return mHandleView;
|
||||
}
|
||||
|
||||
Workspace getWorkspace() {
|
||||
return mWorkspace;
|
||||
}
|
||||
@@ -1885,22 +1785,14 @@ public final class Launcher extends Activity
|
||||
return mAllAppsGrid.isVisible();
|
||||
}
|
||||
|
||||
boolean isAllAppsOpaque() {
|
||||
return mAllAppsGrid.isOpaque();
|
||||
}
|
||||
|
||||
void showAllApps(boolean animated) {
|
||||
mAllAppsGrid.zoom(1.0f, animated);
|
||||
//mWorkspace.hide();
|
||||
|
||||
mWorkspace.startFading(false);
|
||||
|
||||
mAllAppsGrid.setFocusable(true);
|
||||
mAllAppsGrid.requestFocus();
|
||||
|
||||
// TODO: fade these two too
|
||||
mDeleteZone.setVisibility(View.GONE);
|
||||
//mHandleView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1943,13 +1835,6 @@ public final class Launcher extends Activity
|
||||
mAllAppsGrid.zoom(0.0f, animated);
|
||||
mAllAppsGrid.setFocusable(false);
|
||||
mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
|
||||
mWorkspace.startFading(true);
|
||||
|
||||
// TODO: fade these two too
|
||||
/*
|
||||
mDeleteZone.setVisibility(View.VISIBLE);
|
||||
mHandleView.setVisibility(View.VISIBLE);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2162,7 +2047,7 @@ public final class Launcher extends Activity
|
||||
switch (item.itemType) {
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||
final View shortcut = createShortcut((ApplicationInfo) item);
|
||||
final View shortcut = createShortcut((ShortcutInfo)item);
|
||||
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
|
||||
false);
|
||||
break;
|
||||
@@ -2304,7 +2189,7 @@ public final class Launcher extends Activity
|
||||
*/
|
||||
public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps) {
|
||||
removeDialog(DIALOG_CREATE_SHORTCUT);
|
||||
mWorkspace.removeShortcutsForPackage(packageName);
|
||||
mWorkspace.removeItemsForPackage(packageName);
|
||||
mAllAppsGrid.removeApps(apps);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ import android.content.ContentValues;
|
||||
class LauncherAppWidgetInfo extends ItemInfo {
|
||||
|
||||
/**
|
||||
* Identifier for this widget when talking with {@link AppWidgetManager} for updates.
|
||||
* Identifier for this widget when talking with
|
||||
* {@link android.appwidget.AppWidgetManager} for updates.
|
||||
*/
|
||||
int appWidgetId;
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.launcher2;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
@@ -26,11 +25,8 @@ import android.os.Handler;
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
public class LauncherApplication extends Application {
|
||||
public final LauncherModel mModel;
|
||||
|
||||
public LauncherApplication() {
|
||||
mModel = new LauncherModel(this);
|
||||
}
|
||||
public LauncherModel mModel;
|
||||
public IconCache mIconCache;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -38,6 +34,9 @@ public class LauncherApplication extends Application {
|
||||
|
||||
super.onCreate();
|
||||
|
||||
mIconCache = new IconCache(this);
|
||||
mModel = new LauncherModel(this, mIconCache);
|
||||
|
||||
// Register intent receivers
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
@@ -80,4 +79,12 @@ public class LauncherApplication extends Application {
|
||||
mModel.initialize(launcher);
|
||||
return mModel;
|
||||
}
|
||||
|
||||
IconCache getIconCache() {
|
||||
return mIconCache;
|
||||
}
|
||||
|
||||
LauncherModel getModel() {
|
||||
return mModel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,27 @@
|
||||
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.Intent.ShortcutIconResource;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
@@ -60,7 +67,10 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
private boolean mBeforeFirstLoad = true;
|
||||
private WeakReference<Callbacks> mCallbacks;
|
||||
|
||||
private AllAppsList mAllAppsList = new AllAppsList();
|
||||
private AllAppsList mAllAppsList;
|
||||
private IconCache mIconCache;
|
||||
|
||||
private Bitmap mDefaultIcon;
|
||||
|
||||
public interface Callbacks {
|
||||
public int getCurrentWorkspaceScreen();
|
||||
@@ -75,8 +85,17 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps);
|
||||
}
|
||||
|
||||
LauncherModel(LauncherApplication app) {
|
||||
LauncherModel(LauncherApplication app, IconCache iconCache) {
|
||||
mApp = app;
|
||||
mAllAppsList = new AllAppsList(iconCache);
|
||||
mIconCache = iconCache;
|
||||
|
||||
mDefaultIcon = Utilities.createIconBitmap(
|
||||
app.getPackageManager().getDefaultActivityIcon(), app);
|
||||
}
|
||||
|
||||
public Bitmap getDefaultIcon() {
|
||||
return Bitmap.createBitmap(mDefaultIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,7 +337,7 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
removed = mAllAppsList.removed;
|
||||
mAllAppsList.removed = new ArrayList<ApplicationInfo>();
|
||||
for (ApplicationInfo info: removed) {
|
||||
AppInfoCache.remove(info.intent.getComponent());
|
||||
mIconCache.remove(info.intent.getComponent());
|
||||
}
|
||||
}
|
||||
if (mAllAppsList.modified.size() > 0) {
|
||||
@@ -602,6 +621,8 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
final Context context = mContext;
|
||||
final ContentResolver contentResolver = context.getContentResolver();
|
||||
final PackageManager manager = context.getPackageManager();
|
||||
final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
|
||||
final boolean isSafeMode = manager.isSafeMode();
|
||||
|
||||
/* TODO
|
||||
if (mLocaleChanged) {
|
||||
@@ -613,6 +634,8 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
mAppWidgets.clear();
|
||||
mFolders.clear();
|
||||
|
||||
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
|
||||
|
||||
final Cursor c = contentResolver.query(
|
||||
LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
|
||||
|
||||
@@ -649,7 +672,7 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
final int displayModeIndex = c.getColumnIndexOrThrow(
|
||||
LauncherSettings.Favorites.DISPLAY_MODE);
|
||||
|
||||
ApplicationInfo info;
|
||||
ShortcutInfo info;
|
||||
String intentDescription;
|
||||
Widget widgetInfo;
|
||||
LauncherAppWidgetInfo appWidgetInfo;
|
||||
@@ -672,15 +695,15 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
|
||||
info = getApplicationInfo(manager, intent, context);
|
||||
info = getShortcutInfo(manager, intent, context);
|
||||
} else {
|
||||
info = getApplicationInfoShortcut(c, context, iconTypeIndex,
|
||||
info = getShortcutInfo(c, context, iconTypeIndex,
|
||||
iconPackageIndex, iconResourceIndex, iconIndex);
|
||||
}
|
||||
|
||||
if (info == null) {
|
||||
info = new ApplicationInfo();
|
||||
info.icon = manager.getDefaultActivityIcon();
|
||||
info = new ShortcutInfo();
|
||||
info.setIcon(getDefaultIcon());
|
||||
}
|
||||
|
||||
if (info != null) {
|
||||
@@ -734,40 +757,50 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
break;
|
||||
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
|
||||
|
||||
id = c.getLong(idIndex);
|
||||
LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
|
||||
Uri uri = Uri.parse(c.getString(uriIndex));
|
||||
|
||||
intentDescription = c.getString(intentIndex);
|
||||
intent = null;
|
||||
if (intentDescription != null) {
|
||||
try {
|
||||
intent = Intent.parseUri(intentDescription, 0);
|
||||
} catch (URISyntaxException e) {
|
||||
// Ignore, a live folder might not have a base intent
|
||||
// Make sure the live folder exists
|
||||
final ProviderInfo providerInfo =
|
||||
context.getPackageManager().resolveContentProvider(
|
||||
uri.getAuthority(), 0);
|
||||
|
||||
if (providerInfo == null && !isSafeMode) {
|
||||
itemsToRemove.add(id);
|
||||
} else {
|
||||
LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
|
||||
|
||||
intentDescription = c.getString(intentIndex);
|
||||
intent = null;
|
||||
if (intentDescription != null) {
|
||||
try {
|
||||
intent = Intent.parseUri(intentDescription, 0);
|
||||
} catch (URISyntaxException e) {
|
||||
// Ignore, a live folder might not have a base intent
|
||||
}
|
||||
}
|
||||
|
||||
liveFolderInfo.title = c.getString(titleIndex);
|
||||
liveFolderInfo.id = id;
|
||||
liveFolderInfo.uri = uri;
|
||||
container = c.getInt(containerIndex);
|
||||
liveFolderInfo.container = container;
|
||||
liveFolderInfo.screen = c.getInt(screenIndex);
|
||||
liveFolderInfo.cellX = c.getInt(cellXIndex);
|
||||
liveFolderInfo.cellY = c.getInt(cellYIndex);
|
||||
liveFolderInfo.baseIntent = intent;
|
||||
liveFolderInfo.displayMode = c.getInt(displayModeIndex);
|
||||
|
||||
loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
|
||||
iconResourceIndex, liveFolderInfo);
|
||||
|
||||
switch (container) {
|
||||
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
|
||||
mItems.add(liveFolderInfo);
|
||||
break;
|
||||
}
|
||||
mFolders.put(liveFolderInfo.id, liveFolderInfo);
|
||||
}
|
||||
|
||||
liveFolderInfo.title = c.getString(titleIndex);
|
||||
liveFolderInfo.id = id;
|
||||
container = c.getInt(containerIndex);
|
||||
liveFolderInfo.container = container;
|
||||
liveFolderInfo.screen = c.getInt(screenIndex);
|
||||
liveFolderInfo.cellX = c.getInt(cellXIndex);
|
||||
liveFolderInfo.cellY = c.getInt(cellYIndex);
|
||||
liveFolderInfo.uri = Uri.parse(c.getString(uriIndex));
|
||||
liveFolderInfo.baseIntent = intent;
|
||||
liveFolderInfo.displayMode = c.getInt(displayModeIndex);
|
||||
|
||||
loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
|
||||
iconResourceIndex, liveFolderInfo);
|
||||
|
||||
switch (container) {
|
||||
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
|
||||
mItems.add(liveFolderInfo);
|
||||
break;
|
||||
}
|
||||
mFolders.put(liveFolderInfo.id, liveFolderInfo);
|
||||
break;
|
||||
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
|
||||
@@ -792,23 +825,33 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
|
||||
// Read all Launcher-specific widget details
|
||||
int appWidgetId = c.getInt(appWidgetIdIndex);
|
||||
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
|
||||
appWidgetInfo.id = c.getLong(idIndex);
|
||||
appWidgetInfo.screen = c.getInt(screenIndex);
|
||||
appWidgetInfo.cellX = c.getInt(cellXIndex);
|
||||
appWidgetInfo.cellY = c.getInt(cellYIndex);
|
||||
appWidgetInfo.spanX = c.getInt(spanXIndex);
|
||||
appWidgetInfo.spanY = c.getInt(spanYIndex);
|
||||
id = c.getLong(idIndex);
|
||||
|
||||
container = c.getInt(containerIndex);
|
||||
if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||
Log.e(TAG, "Widget found where container "
|
||||
+ "!= CONTAINER_DESKTOP -- ignoring!");
|
||||
continue;
|
||||
final AppWidgetProviderInfo provider =
|
||||
widgets.getAppWidgetInfo(appWidgetId);
|
||||
|
||||
if (!isSafeMode && (provider == null || provider.provider == null ||
|
||||
provider.provider.getPackageName() == null)) {
|
||||
itemsToRemove.add(id);
|
||||
} else {
|
||||
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
|
||||
appWidgetInfo.id = id;
|
||||
appWidgetInfo.screen = c.getInt(screenIndex);
|
||||
appWidgetInfo.cellX = c.getInt(cellXIndex);
|
||||
appWidgetInfo.cellY = c.getInt(cellYIndex);
|
||||
appWidgetInfo.spanX = c.getInt(spanXIndex);
|
||||
appWidgetInfo.spanY = c.getInt(spanYIndex);
|
||||
|
||||
container = c.getInt(containerIndex);
|
||||
if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||
Log.e(TAG, "Widget found where container "
|
||||
+ "!= CONTAINER_DESKTOP -- ignoring!");
|
||||
continue;
|
||||
}
|
||||
appWidgetInfo.container = c.getInt(containerIndex);
|
||||
|
||||
mAppWidgets.add(appWidgetInfo);
|
||||
}
|
||||
appWidgetInfo.container = c.getInt(containerIndex);
|
||||
|
||||
mAppWidgets.add(appWidgetInfo);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -818,6 +861,25 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
|
||||
if (itemsToRemove.size() > 0) {
|
||||
ContentProviderClient client = contentResolver.acquireContentProviderClient(
|
||||
LauncherSettings.Favorites.CONTENT_URI);
|
||||
// Remove dead items
|
||||
for (long id : itemsToRemove) {
|
||||
if (DEBUG_LOADERS) {
|
||||
Log.d(TAG, "Removed id = " + id);
|
||||
}
|
||||
// Don't notify content observers
|
||||
try {
|
||||
client.delete(LauncherSettings.Favorites.getContentUri(id, false),
|
||||
null, null);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Could not remove id = " + id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_LOADERS) {
|
||||
Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
|
||||
}
|
||||
@@ -945,9 +1007,7 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
return;
|
||||
}
|
||||
|
||||
final Context context = mContext;
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
|
||||
final PackageManager packageManager = mContext.getPackageManager();
|
||||
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
|
||||
|
||||
synchronized (mLock) {
|
||||
@@ -958,10 +1018,9 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
long t = SystemClock.uptimeMillis();
|
||||
|
||||
int N = apps.size();
|
||||
Utilities.BubbleText bubble = new Utilities.BubbleText(context);
|
||||
for (int i=0; i<N && !mStopped; i++) {
|
||||
// This builds the icon bitmaps.
|
||||
mAllAppsList.add(AppInfoCache.cache(apps.get(i), context, bubble));
|
||||
mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
|
||||
}
|
||||
Collections.sort(mAllAppsList.data, APP_NAME_COMPARATOR);
|
||||
Collections.sort(mAllAppsList.added, APP_NAME_COMPARATOR);
|
||||
@@ -976,7 +1035,7 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
private void bindAllApps() {
|
||||
synchronized (mLock) {
|
||||
final ArrayList<ApplicationInfo> results
|
||||
= (ArrayList<ApplicationInfo>)mAllAppsList.data.clone();
|
||||
= (ArrayList<ApplicationInfo>) mAllAppsList.data.clone();
|
||||
// We're adding this now, so clear out this so we don't re-send them.
|
||||
mAllAppsList.added = new ArrayList<ApplicationInfo>();
|
||||
mHandler.post(new Runnable() {
|
||||
@@ -991,7 +1050,7 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
|
||||
if (DEBUG_LOADERS) {
|
||||
Log.d(TAG, "bound app " + count + " icons in "
|
||||
+ (SystemClock.uptimeMillis()-t) + "ms");
|
||||
+ (SystemClock.uptimeMillis() - t) + "ms");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1022,9 +1081,9 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an ApplicationInfo object for an application.
|
||||
* Make an ShortcutInfo object for a sortcut that is an application.
|
||||
*/
|
||||
private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent,
|
||||
public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
|
||||
Context context) {
|
||||
final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
|
||||
|
||||
@@ -1032,26 +1091,26 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ApplicationInfo info = new ApplicationInfo();
|
||||
final ShortcutInfo info = new ShortcutInfo();
|
||||
final ActivityInfo activityInfo = resolveInfo.activityInfo;
|
||||
info.icon = Utilities.createIconThumbnail(activityInfo.loadIcon(manager), context);
|
||||
info.setIcon(mIconCache.getIcon(intent.getComponent(), resolveInfo));
|
||||
if (info.title == null || info.title.length() == 0) {
|
||||
info.title = activityInfo.loadLabel(manager);
|
||||
}
|
||||
if (info.title == null) {
|
||||
info.title = "";
|
||||
info.title = activityInfo.name;
|
||||
}
|
||||
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an ApplicationInfo object for a sortcut
|
||||
* Make an ShortcutInfo object for a shortcut that isn't an application.
|
||||
*/
|
||||
private static ApplicationInfo getApplicationInfoShortcut(Cursor c, Context context,
|
||||
private ShortcutInfo getShortcutInfo(Cursor c, Context context,
|
||||
int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) {
|
||||
|
||||
final ApplicationInfo info = new ApplicationInfo();
|
||||
final ShortcutInfo info = new ShortcutInfo();
|
||||
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
|
||||
|
||||
int iconType = c.getInt(iconTypeIndex);
|
||||
@@ -1063,9 +1122,9 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
try {
|
||||
Resources resources = packageManager.getResourcesForApplication(packageName);
|
||||
final int id = resources.getIdentifier(resourceName, null, null);
|
||||
info.icon = Utilities.createIconThumbnail(resources.getDrawable(id), context);
|
||||
info.setIcon(Utilities.createIconBitmap(resources.getDrawable(id), context));
|
||||
} catch (Exception e) {
|
||||
info.icon = packageManager.getDefaultActivityIcon();
|
||||
info.setIcon(getDefaultIcon());
|
||||
}
|
||||
info.iconResource = new Intent.ShortcutIconResource();
|
||||
info.iconResource.packageName = packageName;
|
||||
@@ -1076,23 +1135,74 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
byte[] data = c.getBlob(iconIndex);
|
||||
try {
|
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
|
||||
info.icon = new FastBitmapDrawable(
|
||||
Utilities.createBitmapThumbnail(bitmap, context));
|
||||
info.setIcon(bitmap);
|
||||
} catch (Exception e) {
|
||||
packageManager = context.getPackageManager();
|
||||
info.icon = packageManager.getDefaultActivityIcon();
|
||||
info.setIcon(getDefaultIcon());
|
||||
}
|
||||
info.filtered = true;
|
||||
info.customIcon = true;
|
||||
break;
|
||||
default:
|
||||
info.icon = context.getPackageManager().getDefaultActivityIcon();
|
||||
info.setIcon(getDefaultIcon());
|
||||
info.customIcon = false;
|
||||
break;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
ShortcutInfo addShortcut(Context context, Intent data,
|
||||
CellLayout.CellInfo cellInfo, boolean notify) {
|
||||
|
||||
final ShortcutInfo info = infoFromShortcutIntent(context, data);
|
||||
addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
|
||||
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
|
||||
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
|
||||
|
||||
Bitmap icon = null;
|
||||
boolean filtered = false;
|
||||
boolean customIcon = false;
|
||||
ShortcutIconResource iconResource = null;
|
||||
|
||||
if (bitmap != null && bitmap instanceof Bitmap) {
|
||||
icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
|
||||
filtered = true;
|
||||
customIcon = true;
|
||||
} else {
|
||||
Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
|
||||
if (extra != null && extra instanceof ShortcutIconResource) {
|
||||
try {
|
||||
iconResource = (ShortcutIconResource) extra;
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
Resources resources = packageManager.getResourcesForApplication(
|
||||
iconResource.packageName);
|
||||
final int id = resources.getIdentifier(iconResource.resourceName, null, null);
|
||||
icon = Utilities.createIconBitmap(resources.getDrawable(id), context);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Could not load shortcut icon: " + extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
icon = getDefaultIcon();
|
||||
}
|
||||
|
||||
final ShortcutInfo info = new ShortcutInfo();
|
||||
info.setIcon(icon);
|
||||
info.title = name;
|
||||
info.intent = intent;
|
||||
info.customIcon = customIcon;
|
||||
info.iconResource = iconResource;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private static void loadLiveFolderIcon(Context context, Cursor c, int iconTypeIndex,
|
||||
int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
|
||||
|
||||
@@ -1105,18 +1215,21 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
try {
|
||||
Resources resources = packageManager.getResourcesForApplication(packageName);
|
||||
final int id = resources.getIdentifier(resourceName, null, null);
|
||||
liveFolderInfo.icon = resources.getDrawable(id);
|
||||
liveFolderInfo.icon = Utilities.createIconBitmap(resources.getDrawable(id),
|
||||
context);
|
||||
} catch (Exception e) {
|
||||
liveFolderInfo.icon =
|
||||
context.getResources().getDrawable(R.drawable.ic_launcher_folder);
|
||||
liveFolderInfo.icon = Utilities.createIconBitmap(
|
||||
context.getResources().getDrawable(R.drawable.ic_launcher_folder),
|
||||
context);
|
||||
}
|
||||
liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
|
||||
liveFolderInfo.iconResource.packageName = packageName;
|
||||
liveFolderInfo.iconResource.resourceName = resourceName;
|
||||
break;
|
||||
default:
|
||||
liveFolderInfo.icon =
|
||||
context.getResources().getDrawable(R.drawable.ic_launcher_folder);
|
||||
liveFolderInfo.icon = Utilities.createIconBitmap(
|
||||
context.getResources().getDrawable(R.drawable.ic_launcher_folder),
|
||||
context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,12 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
import android.util.AttributeSet;
|
||||
@@ -58,7 +61,7 @@ public class LauncherProvider extends ContentProvider {
|
||||
|
||||
private static final String DATABASE_NAME = "launcher.db";
|
||||
|
||||
private static final int DATABASE_VERSION = 6;
|
||||
private static final int DATABASE_VERSION = 8;
|
||||
|
||||
static final String AUTHORITY = "com.android.launcher2.settings";
|
||||
|
||||
@@ -382,7 +385,15 @@ public class LauncherProvider extends ContentProvider {
|
||||
version = 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (version < 8) {
|
||||
// Version 8 (froyo) has the icons all normalized. This should
|
||||
// already be the case in practice, but we now rely on it and don't
|
||||
// resample the images each time.
|
||||
normalizeIcons(db);
|
||||
version = 8;
|
||||
}
|
||||
|
||||
if (version != DATABASE_VERSION) {
|
||||
Log.w(TAG, "Destroying all old data.");
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
|
||||
@@ -457,10 +468,64 @@ public class LauncherProvider extends ContentProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void normalizeIcons(SQLiteDatabase db) {
|
||||
Log.d(TAG, "normalizing icons");
|
||||
|
||||
db.beginTransaction();
|
||||
Cursor c = null;
|
||||
try {
|
||||
boolean logged = false;
|
||||
final ContentValues values = new ContentValues();
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
final SQLiteStatement update = db.compileStatement("UPDATE favorites "
|
||||
+ "SET icon=? WHERE _id=?");
|
||||
|
||||
c = db.rawQuery("SELECT _id, icon FROM favorites WHERE iconType=" +
|
||||
Favorites.ICON_TYPE_BITMAP, null);
|
||||
|
||||
final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
|
||||
final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON);
|
||||
|
||||
while (c.moveToNext()) {
|
||||
long id = c.getLong(idIndex);
|
||||
byte[] data = c.getBlob(iconIndex);
|
||||
try {
|
||||
Bitmap bitmap = Utilities.resampleIconBitmap(
|
||||
BitmapFactory.decodeByteArray(data, 0, data.length),
|
||||
mContext);
|
||||
if (bitmap != null) {
|
||||
update.bindLong(1, id);
|
||||
data = ItemInfo.flattenBitmap(bitmap);
|
||||
if (data != null) {
|
||||
update.bindBlob(2, data);
|
||||
update.execute();
|
||||
}
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!logged) {
|
||||
Log.e(TAG, "Failed normalizing icon " + id, e);
|
||||
} else {
|
||||
Log.e(TAG, "Also failed normalizing icon " + id);
|
||||
}
|
||||
logged = true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex);
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade existing clock and photo frame widgets into their new widget
|
||||
* equivalents. This method allocates appWidgetIds, and then hands off to
|
||||
* LauncherAppWidgetBinder to finish the actual binding.
|
||||
* equivalents.
|
||||
*/
|
||||
private void convertWidgets(SQLiteDatabase db) {
|
||||
final int[] bindSources = new int[] {
|
||||
|
||||
@@ -91,8 +91,7 @@ class LauncherSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Favorites. When changing these values, be sure to update
|
||||
* {@link com.android.settings.LauncherAppWidgetBinder} as needed.
|
||||
* Favorites.
|
||||
*/
|
||||
static final class Favorites implements BaseLauncherColumns {
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.graphics.drawable.PaintDrawable;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BlurMaskFilter;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.MaskFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.PixelFormat;
|
||||
@@ -52,15 +51,10 @@ final class Utilities {
|
||||
private static int sIconTextureWidth = -1;
|
||||
private static int sIconTextureHeight = -1;
|
||||
|
||||
private static int sTitleMargin = -1;
|
||||
private static float sBlurRadius = -1;
|
||||
private static Rect sIconTextureRect;
|
||||
|
||||
private static final Paint sPaint = new Paint();
|
||||
private static final Paint sBlurPaint = new Paint();
|
||||
private static final Paint sGlowColorPressedPaint = new Paint();
|
||||
private static final Paint sGlowColorFocusedPaint = new Paint();
|
||||
private static final Paint sEmptyPaint = new Paint();
|
||||
private static final Rect sBounds = new Rect();
|
||||
private static final Rect sOldBounds = new Rect();
|
||||
private static final Canvas sCanvas = new Canvas();
|
||||
@@ -91,87 +85,6 @@ final class Utilities {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Drawable representing the thumbnail of the specified Drawable.
|
||||
* The size of the thumbnail is defined by the dimension
|
||||
* android.R.dimen.launcher_application_icon_size.
|
||||
*
|
||||
* @param icon The icon to get a thumbnail of.
|
||||
* @param context The application's context.
|
||||
*
|
||||
* @return A thumbnail for the specified icon or the icon itself if the
|
||||
* thumbnail could not be created.
|
||||
*/
|
||||
static Drawable createIconThumbnail(Drawable icon, Context context) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
initStatics(context);
|
||||
}
|
||||
|
||||
int width = sIconWidth;
|
||||
int height = sIconHeight;
|
||||
|
||||
if (icon instanceof PaintDrawable) {
|
||||
PaintDrawable painter = (PaintDrawable) icon;
|
||||
painter.setIntrinsicWidth(width);
|
||||
painter.setIntrinsicHeight(height);
|
||||
} else if (icon instanceof BitmapDrawable) {
|
||||
// Ensure the bitmap has a density.
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
|
||||
Bitmap bitmap = bitmapDrawable.getBitmap();
|
||||
if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
|
||||
bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());
|
||||
}
|
||||
}
|
||||
int iconWidth = icon.getIntrinsicWidth();
|
||||
int iconHeight = icon.getIntrinsicHeight();
|
||||
|
||||
if (iconWidth > 0 && iconHeight > 0) {
|
||||
if (width < iconWidth || height < iconHeight) {
|
||||
final float ratio = (float) iconWidth / iconHeight;
|
||||
|
||||
if (iconWidth > iconHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (iconHeight > iconWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
|
||||
final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?
|
||||
Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
|
||||
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
|
||||
final Canvas canvas = sCanvas;
|
||||
canvas.setBitmap(thumb);
|
||||
// Copy the old bounds to restore them later
|
||||
// If we were to do oldBounds = icon.getBounds(),
|
||||
// the call to setBounds() that follows would
|
||||
// change the same instance and we would lose the
|
||||
// old bounds
|
||||
sOldBounds.set(icon.getBounds());
|
||||
final int x = (sIconWidth - width) / 2;
|
||||
final int y = (sIconHeight - height) / 2;
|
||||
icon.setBounds(x, y, x + width, y + height);
|
||||
icon.draw(canvas);
|
||||
icon.setBounds(sOldBounds);
|
||||
icon = new FastBitmapDrawable(thumb);
|
||||
} else if (iconWidth < width && iconHeight < height) {
|
||||
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
|
||||
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
|
||||
final Canvas canvas = sCanvas;
|
||||
canvas.setBitmap(thumb);
|
||||
sOldBounds.set(icon.getBounds());
|
||||
final int x = (width - iconWidth) / 2;
|
||||
final int y = (height - iconHeight) / 2;
|
||||
icon.setBounds(x, y, x + iconWidth, y + iconHeight);
|
||||
icon.draw(canvas);
|
||||
icon.setBounds(sOldBounds);
|
||||
icon = new FastBitmapDrawable(thumb);
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
|
||||
static int sColorIndex = 0;
|
||||
|
||||
@@ -179,8 +92,7 @@ final class Utilities {
|
||||
* Returns a bitmap suitable for the all apps view. The bitmap will be a power
|
||||
* of two sized ARGB_8888 bitmap that can be used as a gl texture.
|
||||
*/
|
||||
static Bitmap createAllAppsBitmap(Drawable icon, String title, BubbleText bubble,
|
||||
Context context) {
|
||||
static Bitmap createIconBitmap(Drawable icon, Context context) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
initStatics(context);
|
||||
@@ -222,8 +134,8 @@ final class Utilities {
|
||||
}
|
||||
|
||||
// no intrinsic size --> use default size
|
||||
final int textureWidth = sIconTextureWidth;
|
||||
final int textureHeight = sIconTextureHeight;
|
||||
int textureWidth = sIconTextureWidth;
|
||||
int textureHeight = sIconTextureHeight;
|
||||
|
||||
final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
@@ -231,7 +143,7 @@ final class Utilities {
|
||||
canvas.setBitmap(bitmap);
|
||||
|
||||
final int left = (textureWidth-width) / 2;
|
||||
final int top = sIconTextureRect.top;
|
||||
final int top = (textureHeight-height) / 2;
|
||||
|
||||
if (false) {
|
||||
// draw a big box for the icon for debugging
|
||||
@@ -247,34 +159,12 @@ final class Utilities {
|
||||
icon.draw(canvas);
|
||||
icon.setBounds(sOldBounds);
|
||||
|
||||
if (title != null) {
|
||||
bubble.drawText(canvas, title);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
static Bitmap extractIconFromTexture(Bitmap src, Context context) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
initStatics(context);
|
||||
}
|
||||
final Bitmap bitmap = Bitmap.createBitmap(sIconWidth, sIconHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
final Canvas canvas = sCanvas;
|
||||
canvas.setBitmap(bitmap);
|
||||
|
||||
Rect r = new Rect(0, 0, sIconWidth, sIconHeight);
|
||||
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
canvas.drawBitmap(src, sIconTextureRect, r, sEmptyPaint);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSelectedAllAppsBitmap(Canvas dest, Bitmap destBitmap,
|
||||
int destWidth, int destHeight, boolean pressed, Bitmap src) {
|
||||
static void drawSelectedAllAppsBitmap(Canvas dest, int destWidth, int destHeight,
|
||||
boolean pressed, Bitmap src) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
// We can't have gotten to here without src being initialized, which
|
||||
@@ -284,14 +174,12 @@ final class Utilities {
|
||||
}
|
||||
|
||||
dest.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
dest.drawBitmap(src, sIconTextureRect, sIconTextureRect, sEmptyPaint);
|
||||
|
||||
int[] xy = new int[2];
|
||||
Bitmap mask = destBitmap.extractAlpha(sBlurPaint, xy);
|
||||
Bitmap mask = src.extractAlpha(sBlurPaint, xy);
|
||||
|
||||
float px = (destWidth - src.getWidth()) / 2;
|
||||
float py = (destHeight - src.getHeight()) / 2;
|
||||
dest.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
dest.drawBitmap(mask, px + xy[0], py + xy[1],
|
||||
pressed ? sGlowColorPressedPaint : sGlowColorFocusedPaint);
|
||||
|
||||
@@ -310,55 +198,17 @@ final class Utilities {
|
||||
* @return A thumbnail for the specified bitmap or the bitmap itself if the
|
||||
* thumbnail could not be created.
|
||||
*/
|
||||
static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context) {
|
||||
static Bitmap resampleIconBitmap(Bitmap bitmap, Context context) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
initStatics(context);
|
||||
}
|
||||
|
||||
int width = sIconWidth;
|
||||
int height = sIconHeight;
|
||||
|
||||
final int bitmapWidth = bitmap.getWidth();
|
||||
final int bitmapHeight = bitmap.getHeight();
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
if (width < bitmapWidth || height < bitmapHeight) {
|
||||
final float ratio = (float) bitmapWidth / bitmapHeight;
|
||||
|
||||
if (bitmapWidth > bitmapHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (bitmapHeight > bitmapWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
|
||||
final Bitmap.Config c = (width == sIconWidth && height == sIconHeight) ?
|
||||
bitmap.getConfig() : Bitmap.Config.ARGB_8888;
|
||||
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
|
||||
final Canvas canvas = sCanvas;
|
||||
final Paint paint = sPaint;
|
||||
canvas.setBitmap(thumb);
|
||||
paint.setDither(false);
|
||||
paint.setFilterBitmap(true);
|
||||
sBounds.set((sIconWidth - width) / 2, (sIconHeight - height) / 2, width, height);
|
||||
sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
|
||||
canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
|
||||
return thumb;
|
||||
} else if (bitmapWidth < width || bitmapHeight < height) {
|
||||
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
|
||||
final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);
|
||||
final Canvas canvas = sCanvas;
|
||||
final Paint paint = sPaint;
|
||||
canvas.setBitmap(thumb);
|
||||
paint.setDither(false);
|
||||
paint.setFilterBitmap(true);
|
||||
canvas.drawBitmap(bitmap, (sIconWidth - bitmapWidth) / 2,
|
||||
(sIconHeight - bitmapHeight) / 2, paint);
|
||||
return thumb;
|
||||
}
|
||||
if (bitmap.getWidth() == sIconWidth && bitmap.getHeight() == sIconHeight) {
|
||||
return bitmap;
|
||||
} else {
|
||||
return createIconBitmap(new BitmapDrawable(bitmap), context);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,13 +218,7 @@ final class Utilities {
|
||||
final float density = metrics.density;
|
||||
|
||||
sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
|
||||
sIconTextureWidth = sIconTextureHeight = roundToPow2(sIconWidth);
|
||||
|
||||
sTitleMargin = (int)(1 * density);
|
||||
sBlurRadius = 5 * density;
|
||||
final int left = (sIconTextureWidth-sIconWidth)/2;
|
||||
final int top = (int)(sBlurRadius) + 1;
|
||||
sIconTextureRect = new Rect(left, top, left+sIconWidth, top+sIconHeight);
|
||||
sIconTextureWidth = sIconTextureHeight = sIconWidth + 2;
|
||||
|
||||
sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
|
||||
sGlowColorPressedPaint.setColor(0xffffc300);
|
||||
@@ -385,79 +229,75 @@ final class Utilities {
|
||||
|
||||
static class BubbleText {
|
||||
private static final int MAX_LINES = 2;
|
||||
private TextPaint mTextPaint;
|
||||
|
||||
private float mBubblePadding;
|
||||
private RectF mBubbleRect = new RectF();
|
||||
private final TextPaint mTextPaint;
|
||||
|
||||
private float mTextWidth;
|
||||
private int mLeading;
|
||||
private int mFirstLineY;
|
||||
private int mLineHeight;
|
||||
private final float mBubblePadding;
|
||||
private final RectF mBubbleRect = new RectF();
|
||||
|
||||
private int mBitmapWidth;
|
||||
private int mBitmapHeight;
|
||||
private final float mTextWidth;
|
||||
private final int mLeading;
|
||||
private final int mFirstLineY;
|
||||
private final int mLineHeight;
|
||||
|
||||
private final int mBitmapWidth;
|
||||
private final int mBitmapHeight;
|
||||
private final int mDensity;
|
||||
|
||||
BubbleText(Context context) {
|
||||
synchronized (sCanvas) { // we share the statics :-(
|
||||
if (sIconWidth == -1) {
|
||||
initStatics(context);
|
||||
}
|
||||
final Resources resources = context.getResources();
|
||||
final Resources resources = context.getResources();
|
||||
|
||||
final float scale = resources.getDisplayMetrics().density;
|
||||
final DisplayMetrics metrics = resources.getDisplayMetrics();
|
||||
final float scale = metrics.density;
|
||||
mDensity = metrics.densityDpi;
|
||||
|
||||
final float paddingLeft = 5.0f * scale;
|
||||
final float paddingRight = 5.0f * scale;
|
||||
final float cellWidth = resources.getDimension(R.dimen.workspace_cell_width);
|
||||
final float bubbleWidth = cellWidth - paddingLeft - paddingRight;
|
||||
mBubblePadding = 3.0f * scale;
|
||||
final float paddingLeft = 5.0f * scale;
|
||||
final float paddingRight = 5.0f * scale;
|
||||
final float cellWidth = resources.getDimension(R.dimen.title_texture_width);
|
||||
final float bubbleWidth = cellWidth - paddingLeft - paddingRight;
|
||||
mBubblePadding = 3.0f * scale;
|
||||
|
||||
RectF bubbleRect = mBubbleRect;
|
||||
bubbleRect.left = 0;
|
||||
bubbleRect.top = 0;
|
||||
bubbleRect.right = (int)(bubbleWidth+0.5f);
|
||||
RectF bubbleRect = mBubbleRect;
|
||||
bubbleRect.left = 0;
|
||||
bubbleRect.top = 0;
|
||||
bubbleRect.right = (int) cellWidth;
|
||||
|
||||
mTextWidth = bubbleWidth - mBubblePadding - mBubblePadding;
|
||||
mTextWidth = bubbleWidth - mBubblePadding - mBubblePadding;
|
||||
|
||||
Paint rectPaint = new Paint();
|
||||
rectPaint.setColor(0xff000000);
|
||||
rectPaint.setAntiAlias(true);
|
||||
TextPaint textPaint = mTextPaint = new TextPaint();
|
||||
textPaint.setTypeface(Typeface.DEFAULT);
|
||||
textPaint.setTextSize(13*scale);
|
||||
textPaint.setColor(0xffffffff);
|
||||
textPaint.setAntiAlias(true);
|
||||
if (TEXT_BURN) {
|
||||
textPaint.setShadowLayer(8, 0, 0, 0xff000000);
|
||||
}
|
||||
|
||||
TextPaint textPaint = mTextPaint = new TextPaint();
|
||||
textPaint.setTypeface(Typeface.DEFAULT);
|
||||
textPaint.setTextSize(13*scale);
|
||||
//textPaint.setColor(0xff00ff00);
|
||||
textPaint.setColor(0xffffffff);
|
||||
textPaint.setAntiAlias(true);
|
||||
if (TEXT_BURN) {
|
||||
textPaint.setShadowLayer(8, 0, 0, 0xff000000);
|
||||
}
|
||||
float ascent = -textPaint.ascent();
|
||||
float descent = textPaint.descent();
|
||||
float leading = 0.0f;//(ascent+descent) * 0.1f;
|
||||
mLeading = (int)(leading + 0.5f);
|
||||
mFirstLineY = (int)(leading + ascent + 0.5f);
|
||||
mLineHeight = (int)(leading + ascent + descent + 0.5f);
|
||||
|
||||
final int iconTop = (int)(sBlurRadius) + 1;
|
||||
final int iconBottom = iconTop + sIconHeight;
|
||||
mBitmapWidth = (int)(mBubbleRect.width() + 0.5f);
|
||||
mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
|
||||
|
||||
float ascent = -textPaint.ascent();
|
||||
float descent = textPaint.descent();
|
||||
float leading = -1.0f;//(ascent+descent) * 0.1f;
|
||||
mLeading = (int)(leading + 0.5f);
|
||||
mFirstLineY = (int)(iconBottom + sTitleMargin + ascent + 0.5f);
|
||||
mLineHeight = (int)(leading + ascent + descent + 0.5f);
|
||||
mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0);
|
||||
|
||||
mBitmapWidth = roundToPow2((int)(mBubbleRect.width() + 0.5f));
|
||||
mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
|
||||
|
||||
mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0);
|
||||
|
||||
if (false) {
|
||||
Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight="
|
||||
+ mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f))
|
||||
+ " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f)));
|
||||
}
|
||||
if (false) {
|
||||
Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight="
|
||||
+ mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f))
|
||||
+ " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f)));
|
||||
}
|
||||
}
|
||||
|
||||
void drawText(Canvas c, String text) {
|
||||
/** You own the bitmap after this and you must call recycle on it. */
|
||||
Bitmap createTextBitmap(String text) {
|
||||
Bitmap b = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ALPHA_8);
|
||||
b.setDensity(mDensity);
|
||||
Canvas c = new Canvas(b);
|
||||
|
||||
StaticLayout layout = new StaticLayout(text, mTextPaint, (int)mTextWidth,
|
||||
Alignment.ALIGN_CENTER, 1, 0, true);
|
||||
int lineCount = layout.getLineCount();
|
||||
@@ -472,12 +312,14 @@ final class Utilities {
|
||||
for (int i=0; i<lineCount; i++) {
|
||||
//int x = (int)((mBubbleRect.width() - layout.getLineMax(i)) / 2.0f);
|
||||
//int y = mFirstLineY + (i * mLineHeight);
|
||||
final String lineText = text.substring(layout.getLineStart(i), layout.getLineEnd(i));
|
||||
int x = (int)(mBubbleRect.left
|
||||
+ ((mBubbleRect.width() - layout.getLineMax(i)) / 2.0f));
|
||||
+ ((mBubbleRect.width() - mTextPaint.measureText(lineText)) * 0.5f));
|
||||
int y = mFirstLineY + (i * mLineHeight);
|
||||
c.drawText(text.substring(layout.getLineStart(i), layout.getLineEnd(i)),
|
||||
x, y, mTextPaint);
|
||||
c.drawText(lineText, x, y, mTextPaint);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private int height(int lineCount) {
|
||||
|
||||
@@ -17,19 +17,21 @@
|
||||
package com.android.launcher2;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Parcel;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
@@ -88,6 +90,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
private OnLongClickListener mLongClickListener;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private IconCache mIconCache;
|
||||
private DragController mDragController;
|
||||
|
||||
/**
|
||||
@@ -103,16 +106,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
private int mTouchSlop;
|
||||
private int mMaximumVelocity;
|
||||
|
||||
final Rect mDrawerBounds = new Rect();
|
||||
final Rect mClipBounds = new Rect();
|
||||
int mDrawerContentHeight;
|
||||
int mDrawerContentWidth;
|
||||
|
||||
private Drawable mPreviousIndicator;
|
||||
private Drawable mNextIndicator;
|
||||
|
||||
private boolean mFading = true;
|
||||
|
||||
/**
|
||||
* Used to inflate the Workspace from XML.
|
||||
*
|
||||
@@ -147,9 +143,12 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
* Initializes various states for this workspace.
|
||||
*/
|
||||
private void initWorkspace() {
|
||||
mScroller = new Scroller(getContext());
|
||||
Context context = getContext();
|
||||
mScroller = new Scroller(context);
|
||||
mCurrentScreen = mDefaultScreen;
|
||||
Launcher.setScreen(mCurrentScreen);
|
||||
LauncherApplication app = (LauncherApplication)context.getApplicationContext();
|
||||
mIconCache = app.getIconCache();
|
||||
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
|
||||
mTouchSlop = configuration.getScaledTouchSlop();
|
||||
@@ -245,27 +244,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
return mCurrentScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many screens there are.
|
||||
*/
|
||||
int getScreenCount() {
|
||||
return getChildCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a bounding rectangle for a range of cells
|
||||
*
|
||||
* @param cellX X coordinate of upper left corner expressed as a cell position
|
||||
* @param cellY Y coordinate of upper left corner expressed as a cell position
|
||||
* @param cellHSpan Width in cells
|
||||
* @param cellVSpan Height in cells
|
||||
* @param rect Rectnagle into which to put the results
|
||||
*/
|
||||
public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF rect) {
|
||||
((CellLayout)getChildAt(mCurrentScreen)).cellToRect(cellX, cellY,
|
||||
cellHSpan, cellVSpan, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current screen.
|
||||
*
|
||||
@@ -275,6 +253,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
if (!mScroller.isFinished()) mScroller.abortAnimation();
|
||||
clearVacantCache();
|
||||
mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
|
||||
mPreviousIndicator.setLevel(mCurrentScreen);
|
||||
mNextIndicator.setLevel(mCurrentScreen);
|
||||
scrollTo(mCurrentScreen * getWidth(), 0);
|
||||
invalidate();
|
||||
}
|
||||
@@ -386,56 +366,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
mVacantCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinate of a vacant cell for the current screen.
|
||||
*/
|
||||
boolean getVacantCell(int[] vacant, int spanX, int spanY) {
|
||||
CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
|
||||
if (group != null) {
|
||||
return group.getVacantCell(vacant, spanX, spanY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified child in the current screen. The position and dimension of
|
||||
* the child are defined by x, y, spanX and spanY.
|
||||
*
|
||||
* @param child The child to add in one of the workspace's screens.
|
||||
* @param spanX The number of cells spanned horizontally by the child.
|
||||
* @param spanY The number of cells spanned vertically by the child.
|
||||
*/
|
||||
void fitInCurrentScreen(View child, int spanX, int spanY) {
|
||||
fitInScreen(child, mCurrentScreen, spanX, spanY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified child in the specified screen. The position and dimension of
|
||||
* the child are defined by x, y, spanX and spanY.
|
||||
*
|
||||
* @param child The child to add in one of the workspace's screens.
|
||||
* @param screen The screen in which to add the child.
|
||||
* @param spanX The number of cells spanned horizontally by the child.
|
||||
* @param spanY The number of cells spanned vertically by the child.
|
||||
*/
|
||||
void fitInScreen(View child, int screen, int spanX, int spanY) {
|
||||
if (screen < 0 || screen >= getChildCount()) {
|
||||
throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount());
|
||||
}
|
||||
|
||||
final CellLayout group = (CellLayout) getChildAt(screen);
|
||||
boolean vacant = group.getVacantCell(mTempCell, spanX, spanY);
|
||||
if (vacant) {
|
||||
group.addView(child,
|
||||
new CellLayout.LayoutParams(mTempCell[0], mTempCell[1], spanX, spanY));
|
||||
child.setHapticFeedbackEnabled(false);
|
||||
child.setOnLongClickListener(mLongClickListener);
|
||||
if (child instanceof DropTarget) {
|
||||
mDragController.addDropTarget((DropTarget)child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the specified listener on each screen contained in this workspace.
|
||||
@@ -477,60 +407,17 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
}
|
||||
}
|
||||
|
||||
public void startFading(boolean dest) {
|
||||
mFading = dest;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
/*
|
||||
final boolean allAppsOpaque = mLauncher.isAllAppsOpaque();
|
||||
if (mFading == allAppsOpaque) {
|
||||
invalidate();
|
||||
} else {
|
||||
mFading = !allAppsOpaque;
|
||||
}
|
||||
if (allAppsOpaque) {
|
||||
// If the launcher is up, draw black.
|
||||
canvas.drawARGB(0xff, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
boolean restore = false;
|
||||
int restoreCount = 0;
|
||||
|
||||
// For the fade. If view gets setAlpha(), use that instead.
|
||||
float scale = mScale;
|
||||
if (scale < 0.999f) {
|
||||
int sx = mScrollX;
|
||||
|
||||
int alpha = (scale < 0.5f) ? (int)(255 * 2 * scale) : 255;
|
||||
|
||||
restoreCount = canvas.saveLayerAlpha(sx, 0, sx+getWidth(), getHeight(), alpha,
|
||||
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
|
||||
restore = true;
|
||||
|
||||
if (scale < 0.999f) {
|
||||
int w = getWidth();
|
||||
w += 2 * mCurrentScreen * w;
|
||||
int dx = w/2;
|
||||
int h = getHeight();
|
||||
int dy = (h/2) - (h/4);
|
||||
canvas.translate(dx, dy);
|
||||
canvas.scale(scale, scale);
|
||||
canvas.translate(-dx, -dy);
|
||||
}
|
||||
}
|
||||
|
||||
// ViewGroup.dispatchDraw() supports many features we don't need:
|
||||
// clip to padding, layout animation, animation listener, disappearing
|
||||
// children, etc. The following implementation attempts to fast-track
|
||||
// the drawing dispatch by drawing only what we know needs to be drawn.
|
||||
|
||||
boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN
|
||||
&& scale > 0.999f;
|
||||
boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
|
||||
// If we are not scrolling or flinging, draw only the current screen
|
||||
if (fastDraw) {
|
||||
drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
|
||||
@@ -555,12 +442,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
}
|
||||
}
|
||||
|
||||
private float mScale = 1.0f;
|
||||
public void setScale(float scale) {
|
||||
mScale = scale;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mDragController.setWindowToken(getWindowToken());
|
||||
@@ -772,12 +653,14 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
case MotionEvent.ACTION_UP:
|
||||
|
||||
if (mTouchState != TOUCH_STATE_SCROLLING) {
|
||||
|
||||
final CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen);
|
||||
if (!currentScreen.lastDownOnOccupiedCell()) {
|
||||
getLocationOnScreen(mTempCell);
|
||||
// Send a tap to the wallpaper if the last down was on empty space
|
||||
mWallpaperManager.sendWallpaperCommand(getWindowToken(),
|
||||
"android.wallpaper.tap", (int) ev.getX(), (int) ev.getY(), 0, null);
|
||||
"android.wallpaper.tap",
|
||||
mTempCell[0] + (int) ev.getX(),
|
||||
mTempCell[1] + (int) ev.getY(), 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,6 +853,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
final int delta = newX - mScrollX;
|
||||
final int duration = screenDelta * 300;
|
||||
awakenScrollBars(duration);
|
||||
|
||||
if (!mScroller.isFinished()) mScroller.abortAnimation();
|
||||
mScroller.startScroll(mScrollX, 0, delta, 0, duration);
|
||||
invalidate();
|
||||
}
|
||||
@@ -1010,11 +895,11 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
}
|
||||
}
|
||||
|
||||
void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo) {
|
||||
void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
|
||||
addApplicationShortcut(info, cellInfo, false);
|
||||
}
|
||||
|
||||
void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo,
|
||||
void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
|
||||
boolean insertAtFirst) {
|
||||
final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
|
||||
final int[] result = new int[2];
|
||||
@@ -1080,10 +965,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||
if (info.container == NO_ID) {
|
||||
// Came from all apps -- make a copy
|
||||
info = new ApplicationInfo((ApplicationInfo) info);
|
||||
info = new ShortcutInfo((ApplicationInfo)info);
|
||||
}
|
||||
view = mLauncher.createShortcut(R.layout.application, cellLayout,
|
||||
(ApplicationInfo) info);
|
||||
view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo)info);
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
|
||||
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
|
||||
@@ -1215,16 +1099,19 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
|
||||
public void scrollLeft() {
|
||||
clearVacantCache();
|
||||
if (mNextScreen == INVALID_SCREEN && mCurrentScreen > 0 && mScroller.isFinished()) {
|
||||
snapToScreen(mCurrentScreen - 1);
|
||||
if (mScroller.isFinished()) {
|
||||
if (mCurrentScreen > 0) snapToScreen(mCurrentScreen - 1);
|
||||
} else {
|
||||
if (mNextScreen > 0) snapToScreen(mNextScreen - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void scrollRight() {
|
||||
clearVacantCache();
|
||||
if (mNextScreen == INVALID_SCREEN && mCurrentScreen < getChildCount() -1 &&
|
||||
mScroller.isFinished()) {
|
||||
snapToScreen(mCurrentScreen + 1);
|
||||
if (mScroller.isFinished()) {
|
||||
if (mCurrentScreen < getChildCount() -1) snapToScreen(mCurrentScreen + 1);
|
||||
} else {
|
||||
if (mNextScreen < getChildCount() -1) snapToScreen(mNextScreen + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1314,74 +1201,105 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
mAllowLongPress = allowLongPress;
|
||||
}
|
||||
|
||||
void removeShortcutsForPackage(String packageName) {
|
||||
final ArrayList<View> childrenToRemove = new ArrayList<View>();
|
||||
void removeItemsForPackage(final String packageName) {
|
||||
final int count = getChildCount();
|
||||
final PackageManager manager = getContext().getPackageManager();
|
||||
final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final CellLayout layout = (CellLayout) getChildAt(i);
|
||||
int childCount = layout.getChildCount();
|
||||
|
||||
childrenToRemove.clear();
|
||||
// Avoid ANRs by treating each screen separately
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
final ArrayList<View> childrenToRemove = new ArrayList<View>();
|
||||
childrenToRemove.clear();
|
||||
|
||||
int childCount = layout.getChildCount();
|
||||
for (int j = 0; j < childCount; j++) {
|
||||
final View view = layout.getChildAt(j);
|
||||
Object tag = view.getTag();
|
||||
|
||||
if (tag instanceof ShortcutInfo) {
|
||||
final ShortcutInfo info = (ShortcutInfo) tag;
|
||||
// We need to check for ACTION_MAIN otherwise getComponent() might
|
||||
// return null for some shortcuts (for instance, for shortcuts to
|
||||
// web pages.)
|
||||
final Intent intent = info.intent;
|
||||
final ComponentName name = intent.getComponent();
|
||||
|
||||
if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
|
||||
name != null && packageName.equals(name.getPackageName())) {
|
||||
// TODO: This should probably be done on a worker thread
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, info);
|
||||
childrenToRemove.add(view);
|
||||
}
|
||||
} else if (tag instanceof UserFolderInfo) {
|
||||
final UserFolderInfo info = (UserFolderInfo) tag;
|
||||
final ArrayList<ShortcutInfo> contents = info.contents;
|
||||
final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
|
||||
final int contentsCount = contents.size();
|
||||
boolean removedFromFolder = false;
|
||||
|
||||
for (int k = 0; k < contentsCount; k++) {
|
||||
final ShortcutInfo appInfo = contents.get(k);
|
||||
final Intent intent = appInfo.intent;
|
||||
final ComponentName name = intent.getComponent();
|
||||
|
||||
if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
|
||||
name != null && packageName.equals(name.getPackageName())) {
|
||||
toRemove.add(appInfo);
|
||||
// TODO: This should probably be done on a worker thread
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
|
||||
removedFromFolder = true;
|
||||
}
|
||||
}
|
||||
|
||||
contents.removeAll(toRemove);
|
||||
if (removedFromFolder) {
|
||||
final Folder folder = getOpenFolder();
|
||||
if (folder != null) folder.notifyDataSetChanged();
|
||||
}
|
||||
} else if (tag instanceof LiveFolderInfo) {
|
||||
final LiveFolderInfo info = (LiveFolderInfo) tag;
|
||||
final Uri uri = info.uri;
|
||||
final ProviderInfo providerInfo = manager.resolveContentProvider(
|
||||
uri.getAuthority(), 0);
|
||||
|
||||
for (int j = 0; j < childCount; j++) {
|
||||
final View view = layout.getChildAt(j);
|
||||
Object tag = view.getTag();
|
||||
|
||||
if (tag instanceof ApplicationInfo) {
|
||||
final ApplicationInfo info = (ApplicationInfo) tag;
|
||||
// We need to check for ACTION_MAIN otherwise getComponent() might
|
||||
// return null for some shortcuts (for instance, for shortcuts to
|
||||
// web pages.)
|
||||
final Intent intent = info.intent;
|
||||
final ComponentName name = intent.getComponent();
|
||||
|
||||
if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
|
||||
name != null && packageName.equals(name.getPackageName())) {
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, info);
|
||||
childrenToRemove.add(view);
|
||||
}
|
||||
} else if (tag instanceof UserFolderInfo) {
|
||||
final UserFolderInfo info = (UserFolderInfo) tag;
|
||||
final ArrayList<ApplicationInfo> contents = info.contents;
|
||||
final ArrayList<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>(1);
|
||||
final int contentsCount = contents.size();
|
||||
boolean removedFromFolder = false;
|
||||
|
||||
for (int k = 0; k < contentsCount; k++) {
|
||||
final ApplicationInfo appInfo = contents.get(k);
|
||||
final Intent intent = appInfo.intent;
|
||||
final ComponentName name = intent.getComponent();
|
||||
|
||||
if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
|
||||
name != null && packageName.equals(name.getPackageName())) {
|
||||
toRemove.add(appInfo);
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
|
||||
removedFromFolder = true;
|
||||
if (providerInfo == null ||
|
||||
packageName.equals(providerInfo.packageName)) {
|
||||
// TODO: This should probably be done on a worker thread
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, info);
|
||||
childrenToRemove.add(view);
|
||||
}
|
||||
} else if (tag instanceof LauncherAppWidgetInfo) {
|
||||
final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
|
||||
final AppWidgetProviderInfo provider =
|
||||
widgets.getAppWidgetInfo(info.appWidgetId);
|
||||
if (provider == null ||
|
||||
packageName.equals(provider.provider.getPackageName())) {
|
||||
// TODO: This should probably be done on a worker thread
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, info);
|
||||
childrenToRemove.add(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contents.removeAll(toRemove);
|
||||
if (removedFromFolder) {
|
||||
final Folder folder = getOpenFolder();
|
||||
if (folder != null) folder.notifyDataSetChanged();
|
||||
|
||||
childCount = childrenToRemove.size();
|
||||
for (int j = 0; j < childCount; j++) {
|
||||
View child = childrenToRemove.get(j);
|
||||
layout.removeViewInLayout(child);
|
||||
if (child instanceof DropTarget) {
|
||||
mDragController.removeDropTarget((DropTarget)child);
|
||||
}
|
||||
}
|
||||
|
||||
if (childCount > 0) {
|
||||
layout.requestLayout();
|
||||
layout.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
childCount = childrenToRemove.size();
|
||||
for (int j = 0; j < childCount; j++) {
|
||||
View child = childrenToRemove.get(j);
|
||||
layout.removeViewInLayout(child);
|
||||
if (child instanceof DropTarget) {
|
||||
mDragController.removeDropTarget((DropTarget)child);
|
||||
}
|
||||
}
|
||||
|
||||
if (childCount > 0) {
|
||||
layout.requestLayout();
|
||||
layout.invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1395,8 +1313,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
for (int j = 0; j < childCount; j++) {
|
||||
final View view = layout.getChildAt(j);
|
||||
Object tag = view.getTag();
|
||||
if (tag instanceof ApplicationInfo) {
|
||||
ApplicationInfo info = (ApplicationInfo) tag;
|
||||
if (tag instanceof ShortcutInfo) {
|
||||
ShortcutInfo info = (ShortcutInfo)tag;
|
||||
// We need to check for ACTION_MAIN otherwise getComponent() might
|
||||
// return null for some shortcuts (for instance, for shortcuts to
|
||||
// web pages.)
|
||||
@@ -1406,14 +1324,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null &&
|
||||
packageName.equals(name.getPackageName())) {
|
||||
|
||||
final Drawable icon = AppInfoCache.getIconDrawable(pm, info);
|
||||
if (icon != null && icon != info.icon) {
|
||||
info.icon.setCallback(null);
|
||||
info.icon = Utilities.createIconThumbnail(icon, mContext);
|
||||
info.filtered = true;
|
||||
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
|
||||
info.icon, null, null);
|
||||
}
|
||||
info.setIcon(mIconCache.getIcon(info.intent));
|
||||
((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
|
||||
new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1465,11 +1378,4 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void show() {
|
||||
setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
void hide() {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user