update promise icon status

also fix a crash in LauncherModel.DEBUG_LOADERS

Bug: 10778992
Change-Id: Iafc28c1e0c2f2a1283783a7ce27e181634b62993
This commit is contained in:
Chris Wren
2014-02-14 16:59:24 -05:00
parent bfbd52a5e6
commit aeff7ea434
9 changed files with 268 additions and 64 deletions
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (C) 2014 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.
*/
-->
<resources>
<integer name="promise_icon_alpha">127</integer>
</resources>
+11
View File
@@ -262,4 +262,15 @@ s -->
<string name="wallpaper_button_text">Wallpapers</string>
<!-- Text for settings button -->
<string name="settings_button_text">Settings</string>
<!-- Label on an icon that references an uninstalled package, that is going to be installed at some point. [CHAR_LIMIT=15] -->
<string name="package_state_enqueued">Waiting</string>
<!-- Label on an icon that references an uninstalled package, that is currently being downloaded. [CHAR_LIMIT=15] -->
<string name="package_state_downloading">Downloading</string>
<!-- Label on an icon that references an uninstalled package, that is currently being installed. [CHAR_LIMIT=15] -->
<string name="package_state_installing">Installing</string>
<!-- Label on an icon that references an uninstalled package, for which we have no information about when it might be installed. [CHAR_LIMIT=15] -->
<string name="package_state_unknown">Unknown</string>
<!-- Label on an icon that references an uninstalled package, for which restore from market has failed. [CHAR_LIMIT=15] -->
<string name="package_state_error">Error</string>
</resources>
+63 -2
View File
@@ -25,6 +25,7 @@ import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.widget.TextView;
@@ -43,6 +44,10 @@ public class BubbleTextView extends TextView {
static final float PADDING_H = 8.0f;
static final float PADDING_V = 3.0f;
private static final String TAG = "BubbleTextView";
private static final boolean DEBUG = false;
private int mPrevAlpha = -1;
private HolographicOutlineHelper mOutlineHelper;
@@ -64,6 +69,11 @@ public class BubbleTextView extends TextView {
private boolean mStayPressed;
private CheckLongPressHelper mLongPressHelper;
private int mInstallState;
private int mState;
private CharSequence mDefaultText = "";
public BubbleTextView(Context context) {
super(context);
@@ -108,11 +118,14 @@ public class BubbleTextView extends TextView {
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
setCompoundDrawables(null,
Utilities.createIconDrawable(b), null, null);
Drawable iconDrawable = Utilities.createIconDrawable(b);
setCompoundDrawables(null, iconDrawable, null, null);
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
setText(info.title);
setTag(info);
if (info.isPromise()) {
setState(ShortcutInfo.PACKAGE_STATE_UNKNOWN); // TODO: persist this state somewhere
}
}
@Override
@@ -392,4 +405,52 @@ public class BubbleTextView extends TextView {
mLongPressHelper.cancelLongPress();
}
public void setState(int state) {
if (mState == ShortcutInfo.PACKAGE_STATE_DEFAULT && mState != state) {
mDefaultText = getText();
}
mState = state;
applyState();
}
private void applyState() {
int alpha = getResources().getInteger(R.integer.promise_icon_alpha);
if (DEBUG) Log.d(TAG, "applying icon state: " + mState);
switch(mState) {
case ShortcutInfo.PACKAGE_STATE_DEFAULT:
super.setText(mDefaultText);
alpha = 255;
break;
case ShortcutInfo.PACKAGE_STATE_ENQUEUED:
setText(R.string.package_state_enqueued);
break;
case ShortcutInfo.PACKAGE_STATE_DOWNLOADING:
setText(R.string.package_state_downloading);
break;
case ShortcutInfo.PACKAGE_STATE_INSTALLING:
setText(R.string.package_state_installing);
break;
case ShortcutInfo.PACKAGE_STATE_ERROR:
setText(R.string.package_state_error);
break;
case ShortcutInfo.PACKAGE_STATE_UNKNOWN:
default:
setText(R.string.package_state_unknown);
break;
}
if (DEBUG) Log.d(TAG, "setting icon alpha to: " + alpha);
Drawable[] drawables = getCompoundDrawables();
for (int i = 0; i < drawables.length; i++) {
if (drawables[i] != null) {
drawables[i].setAlpha(alpha);
}
}
}
}
-14
View File
@@ -387,20 +387,6 @@ public class IconCache {
}
}
if (icon != null) {
// TODO: handle alpha mask in the view layer
Bitmap b = Bitmap.createBitmap(Math.max(icon.getWidth(), 1),
Math.max(icon.getHeight(), 1),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
Paint paint = new Paint();
paint.setAlpha(127);
c.drawBitmap(icon, 0, 0, paint);
c.setBitmap(null);
icon.recycle();
icon = b;
}
return icon;
}
+11
View File
@@ -4222,6 +4222,17 @@ public class Launcher extends Activity
}
}
/**
* Update the state of a package, typically related to install state.
*
* Implementation of the method from LauncherModel.Callbacks.
*/
public void updatePackageState(String pkgName, int state) {
if (mWorkspace != null) {
mWorkspace.updatePackageState(pkgName, state);
}
}
/**
* A package was uninstalled. We take both the super set of packageNames
* in addition to specific applications to remove, the reason being that
@@ -30,6 +30,8 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
private static final String TAG = "LauncherAppState";
private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
private static final boolean DEBUG = true; // TODO STOPSHIP: set this to false
private final AppFilter mAppFilter;
private final BuildInfo mBuildInfo;
private LauncherModel mModel;
@@ -249,4 +251,9 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
public static boolean isDogfoodBuild() {
return getInstance().mBuildInfo.isDogfoodBuild();
}
public void setPackageState(String pkgName, int state) {
if (DEBUG) Log.d(TAG, "setPackageState(" + pkgName + ", " + state + ")");
mModel.setPackageState(pkgName, state);
}
}
+20 -1
View File
@@ -173,6 +173,7 @@ public class LauncherModel extends BroadcastReceiver {
ArrayList<ItemInfo> addAnimated,
ArrayList<AppInfo> addedApps);
public void bindAppsUpdated(ArrayList<AppInfo> apps);
public void updatePackageState(String pkgName, int state);
public void bindComponentsRemoved(ArrayList<String> packageNames,
ArrayList<AppInfo> appInfos);
public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
@@ -296,6 +297,19 @@ public class LauncherModel extends BroadcastReceiver {
return null;
}
public void setPackageState(final String pkgName, final int state) {
// Process the updated package state
Runnable r = new Runnable() {
public void run() {
Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
if (callbacks != null) {
callbacks.updatePackageState(pkgName, state);
}
}
};
mHandler.post(r);
}
public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {
final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
@@ -2193,7 +2207,12 @@ public class LauncherModel extends BroadcastReceiver {
line += " | ";
}
for (int x = 0; x < countX; x++) {
line += ((occupied.get(screenId)[x][y] != null) ? "#" : ".");
ItemInfo[][] screen = occupied.get(screenId);
if (x < screen.length && y < screen[x].length) {
line += (screen[x][y] != null) ? "#" : ".";
} else {
line += "!";
}
}
}
Log.d(TAG, "[ " + line + " ]");
@@ -33,6 +33,24 @@ import java.util.ArrayList;
*/
public class ShortcutInfo extends ItemInfo {
/** This package is not installed, and there is no other information available. */
public static final int PACKAGE_STATE_UNKNOWN = -2;
/** This package is not installed, because installation failed. */
public static final int PACKAGE_STATE_ERROR = -1;
/** This package is installed. This is the typical case */
public static final int PACKAGE_STATE_DEFAULT = 0;
/** This package is not installed, but some external entity has promised to install it. */
public static final int PACKAGE_STATE_ENQUEUED = 1;
/** This package is not installed, but some external entity is downloading it. */
public static final int PACKAGE_STATE_DOWNLOADING = 2;
/** This package is not installed, but some external entity is installing it. */
public static final int PACKAGE_STATE_INSTALLING = 3;
/**
* The intent used to start the application.
*/
@@ -219,5 +237,15 @@ public class ShortcutInfo extends ItemInfo {
+ " customIcon=" + info.customIcon);
}
}
public boolean isPromise() {
return restoredIntent != null;
}
public boolean isPromiseFor(String pkgName) {
return restoredIntent != null
&& pkgName != null
&& pkgName.equals(restoredIntent.getComponent().getPackageName());
}
}
+106 -47
View File
@@ -96,6 +96,9 @@ public class Workspace extends SmoothPagedView
private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
private static final boolean MAP_NO_RECURSE = false;
private static final boolean MAP_RECURSE = true;
// These animators are used to fade the children's outlines
private ObjectAnimator mChildrenOutlineFadeInAnimation;
private ObjectAnimator mChildrenOutlineFadeOutAnimation;
@@ -4452,51 +4455,50 @@ public class Workspace extends SmoothPagedView
return childrenLayouts;
}
public Folder getFolderForTag(Object tag) {
ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
getAllShortcutAndWidgetContainers();
for (ShortcutAndWidgetContainer layout: childrenLayouts) {
int count = layout.getChildCount();
for (int i = 0; i < count; i++) {
View child = layout.getChildAt(i);
if (child instanceof Folder) {
Folder f = (Folder) child;
public Folder getFolderForTag(final Object tag) {
final Folder[] value = new Folder[1];
mapOverShortcuts(MAP_NO_RECURSE, new ShortcutOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
if (v instanceof Folder) {
Folder f = (Folder) v;
if (f.getInfo() == tag && f.getInfo().opened) {
return f;
value[0] = f;
return true;
}
}
return false;
}
}
return null;
});
return value[0];
}
public View getViewForTag(Object tag) {
ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
getAllShortcutAndWidgetContainers();
for (ShortcutAndWidgetContainer layout: childrenLayouts) {
int count = layout.getChildCount();
for (int i = 0; i < count; i++) {
View child = layout.getChildAt(i);
if (child.getTag() == tag) {
return child;
public View getViewForTag(final Object tag) {
final View[] value = new View[1];
mapOverShortcuts(MAP_NO_RECURSE, new ShortcutOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
if (v.getTag() == tag) {
value[0] = v;
return true;
}
return false;
}
}
return null;
});
return value[0];
}
void clearDropTargets() {
ArrayList<ShortcutAndWidgetContainer> childrenLayouts =
getAllShortcutAndWidgetContainers();
for (ShortcutAndWidgetContainer layout: childrenLayouts) {
int childCount = layout.getChildCount();
for (int j = 0; j < childCount; j++) {
View v = layout.getChildAt(j);
mapOverShortcuts(MAP_NO_RECURSE, new ShortcutOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
if (v instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) v);
}
// not done, process all the shortcuts
return false;
}
}
});
}
// Removes ALL items that match a given package name, this is usually called when a package
@@ -4638,6 +4640,55 @@ public class Workspace extends SmoothPagedView
}
}
interface ShortcutOperator {
/**
* Process the next shortcut, possibly with side-effect on {@link ShortcutOperator#value}.
*
* @param info info for the shortcut
* @param view view for the shortcut
* @param parent containing folder, or null
* @return true if done, false to continue the map
*/
public boolean evaluate(ItemInfo info, View view, View parent);
}
/**
* Map the operator over the shortcuts, return the first-non-null value.
*
* @param recurse true: iterate over folder children. false: op get the folders themselves.
* @param op the operator to map over the shortcuts
*/
void mapOverShortcuts(boolean recurse, ShortcutOperator op) {
ArrayList<ShortcutAndWidgetContainer> containers = getAllShortcutAndWidgetContainers();
final int containerCount = containers.size();
for (int containerIdx = 0; containerIdx < containerCount; containerIdx++) {
ShortcutAndWidgetContainer container = containers.get(containerIdx);
// map over all the shortcuts on the workspace
final int itemCount = container.getChildCount();
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
View item = container.getChildAt(itemIdx);
ItemInfo info = (ItemInfo) item.getTag();
if (recurse && info instanceof FolderInfo && item instanceof FolderIcon) {
FolderIcon folder = (FolderIcon) item;
ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder();
// map over all the children in the folder
final int childCount = folderChildren.size();
for (int childIdx = 0; childIdx < childCount; childIdx++) {
View child = folderChildren.get(childIdx);
info = (ItemInfo) child.getTag();
if (op.evaluate(info, child, folder)) {
return;
}
}
} else {
if (op.evaluate(info, item, null)) {
return;
}
}
}
}
}
void updateShortcuts(ArrayList<AppInfo> apps) {
// Create a map of the apps to test against
final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
@@ -4645,26 +4696,34 @@ public class Workspace extends SmoothPagedView
appsMap.put(ai.componentName, ai);
}
ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers();
for (ShortcutAndWidgetContainer layout: childrenLayouts) {
// Update all the children shortcuts
final HashMap<ItemInfo, View> children = new HashMap<ItemInfo, View>();
for (int j = 0; j < layout.getChildCount(); j++) {
View v = layout.getChildAt(j);
ItemInfo info = (ItemInfo) v.getTag();
if (info instanceof FolderInfo && v instanceof FolderIcon) {
FolderIcon folder = (FolderIcon) v;
ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder();
for (View fv : folderChildren) {
info = (ItemInfo) fv.getTag();
updateShortcut(appsMap, info, fv);
}
folder.invalidate();
} else if (info instanceof ShortcutInfo) {
mapOverShortcuts(MAP_RECURSE, new ShortcutOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
if (info instanceof ShortcutInfo) {
updateShortcut(appsMap, info, v);
if (parent != null) {
parent.invalidate();
}
}
// process all the shortcuts
return false;
}
}
});
}
public void updatePackageState(final String pkgName, final int state) {
mapOverShortcuts(MAP_RECURSE, new ShortcutOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
if (info instanceof ShortcutInfo
&& ((ShortcutInfo) info).isPromiseFor(pkgName)
&& v instanceof BubbleTextView) {
((BubbleTextView)v).setState(state);
}
// process all the shortcuts
return false;
}
});
}
private void moveToScreen(int page, boolean animate) {