Stripping LiveFolders from Launcher

Change-Id: Ic105fbeb1289e43469d5975b7d977b2fc7900c0b
This commit is contained in:
Adam Cohen
2011-04-27 16:56:57 -07:00
parent 9e87bd8ee7
commit df2cc41acb
18 changed files with 385 additions and 1270 deletions
+2 -2
View File
@@ -14,7 +14,7 @@
limitations under the License.
-->
<com.android.launcher2.UserFolder
<com.android.launcher2.Folder
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:orientation="vertical">
@@ -58,4 +58,4 @@
android:numColumns="5" />
</FrameLayout>
</com.android.launcher2.UserFolder>
</com.android.launcher2.Folder>
+2 -2
View File
@@ -14,7 +14,7 @@
limitations under the License.
-->
<com.android.launcher2.UserFolder
<com.android.launcher2.Folder
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
android:orientation="vertical">
@@ -57,4 +57,4 @@
android:numColumns="4" />
</FrameLayout>
</com.android.launcher2.UserFolder>
</com.android.launcher2.Folder>
@@ -40,7 +40,6 @@ public class AddAdapter extends BaseAdapter {
public static final int ITEM_SHORTCUT = 0;
public static final int ITEM_APPWIDGET = 1;
public static final int ITEM_LIVE_FOLDER = 2;
public static final int ITEM_WALLPAPER = 3;
/**
@@ -76,9 +75,6 @@ public class AddAdapter extends BaseAdapter {
mItems.add(new ListItem(res, R.string.group_widgets,
R.drawable.ic_launcher_appwidget, ITEM_APPWIDGET));
mItems.add(new ListItem(res, R.string.group_live_folders,
R.drawable.ic_launcher_folder, ITEM_LIVE_FOLDER));
mItems.add(new ListItem(res, R.string.group_wallpapers,
R.drawable.ic_launcher_wallpaper, ITEM_WALLPAPER));
+9 -10
View File
@@ -16,9 +16,9 @@
package com.android.launcher2;
import android.animation.AnimatorSet;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -31,7 +31,6 @@ import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.TranslateAnimation;
import com.android.launcher.R;
@@ -113,18 +112,18 @@ public class DeleteZone extends IconDropTarget {
if (item instanceof LauncherAppWidgetInfo) {
mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
}
} else if (source instanceof UserFolder) {
final UserFolder userFolder = (UserFolder) source;
final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();
} else if (source instanceof Folder) {
final Folder folder = (Folder) source;
final FolderInfo folderInfo = (FolderInfo) folder.getInfo();
// Item must be a ShortcutInfo otherwise it couldn't have been in the folder
// in the first place.
userFolderInfo.remove((ShortcutInfo)item);
folderInfo.remove((ShortcutInfo)item);
}
if (item instanceof UserFolderInfo) {
final UserFolderInfo userFolderInfo = (UserFolderInfo)item;
LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo);
mLauncher.removeFolder(userFolderInfo);
if (item instanceof FolderInfo) {
final FolderInfo folderInfo = (FolderInfo)item;
LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
mLauncher.removeFolder(folderInfo);
} else if (item instanceof LauncherAppWidgetInfo) {
final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
+284 -14
View File
@@ -16,14 +16,25 @@
package com.android.launcher2;
import java.util.ArrayList;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
@@ -33,14 +44,14 @@ import com.android.launcher.R;
* Represents a set of icons chosen by the user or generated by the system.
*/
public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
OnItemClickListener, OnClickListener, View.OnLongClickListener {
OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget {
protected DragController mDragController;
protected Launcher mLauncher;
protected Button mCloseButton;
protected FolderInfo mInfo;
/**
@@ -48,6 +59,19 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
*/
protected ShortcutInfo mDragItem;
private static final String TAG = "Launcher.Folder";
static final int STATE_NONE = -1;
static final int STATE_SMALL = 0;
static final int STATE_ANIMATING = 1;
static final int STATE_OPEN = 2;
private int mExpandDuration;
protected CellLayout mContent;
private final LayoutInflater mInflater;
private final IconCache mIconCache;
private int mState = STATE_NONE;
/**
* Used to inflate the Workspace from XML.
*
@@ -57,6 +81,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
public Folder(Context context, AttributeSet attrs) {
super(context, attrs);
setAlwaysDrawnWithCacheEnabled(false);
mInflater = LayoutInflater.from(context);
mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
}
@Override
@@ -66,6 +93,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
mCloseButton = (Button) findViewById(R.id.folder_close);
mCloseButton.setOnClickListener(this);
mCloseButton.setOnLongClickListener(this);
mContent = (CellLayout) findViewById(R.id.folder_content);
}
public void onItemClick(AdapterView parent, View v, int position, long id) {
@@ -78,12 +106,38 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
public void onClick(View v) {
mLauncher.closeFolder(this);
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// refactor this code from Folder
ShortcutInfo item = (ShortcutInfo) tag;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
item.intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
mLauncher.startActivitySafely(item.intent, item);
} else {
mLauncher.closeFolder(this);
}
}
public boolean onLongClick(View v) {
mLauncher.closeFolder(this);
mLauncher.showRenameDialog(mInfo);
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// refactor this code from Folder
ShortcutInfo item = (ShortcutInfo) tag;
if (!v.isInTouchMode()) {
return false;
}
mLauncher.getWorkspace().onDragStartedWithItem(v);
mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
mLauncher.closeFolder(this);
mDragItem = item;
} else {
mLauncher.closeFolder(this);
mLauncher.showRenameDialog(mInfo);
}
return true;
}
@@ -105,17 +159,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
mDragController = dragController;
}
@Override
public void onDropCompleted(View target, Object dragInfo, boolean success) {
}
@Override
public void onDragViewVisible() {
}
void notifyDataSetChanged() {
}
void setLauncher(Launcher launcher) {
mLauncher = launcher;
}
@@ -128,6 +174,11 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
void onOpen() {
// When the folder opens, we need to refresh the GridView's selection by
// forcing a layout
// TODO: find out if this is still necessary
mContent.requestLayout();
requestFocus();
}
void onClose() {
@@ -138,5 +189,224 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
void bind(FolderInfo info) {
mInfo = info;
mCloseButton.setText(info.title);
ArrayList<ShortcutInfo> children = info.contents;
for (int i = 0; i < children.size(); i++) {
ShortcutInfo child = (ShortcutInfo) children.get(i);
if ((child.cellX == -1 && child.cellY == -1) ||
mContent.isOccupied(child.cellX, child.cellY)) {
findAndSetEmptyCells(child);
}
createAndAddShortcut((ShortcutInfo) children.get(i));
}
}
/**
* Creates a new UserFolder, inflated from R.layout.user_folder.
*
* @param context The application's context.
*
* @return A new UserFolder.
*/
static Folder fromXml(Context context) {
return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
}
/**
* This method is intended to make the UserFolder to be visually identical in size and position
* to its associated FolderIcon. This allows for a seamless transition into the expanded state.
*/
private void positionAndSizeAsIcon() {
if (!(getParent() instanceof CellLayoutChildren)) return;
CellLayoutChildren clc = (CellLayoutChildren) getParent();
CellLayout cellLayout = (CellLayout) clc.getParent();
FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
lp.width = iconLp.width;
lp.height = iconLp.height;
lp.x = iconLp.x;
lp.y = iconLp.y;
mContent.setAlpha(0f);
mState = STATE_SMALL;
}
public void animateOpen() {
if (mState != STATE_SMALL) {
positionAndSizeAsIcon();
}
if (!(getParent() instanceof CellLayoutChildren)) return;
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
CellLayoutChildren clc = (CellLayoutChildren) getParent();
CellLayout cellLayout = (CellLayout) clc.getParent();
Rect r = cellLayout.getContentRect(null);
PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", r.width());
PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", r.height());
PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", 0);
PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", 0);
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
oa.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
requestLayout();
}
});
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
AnimatorSet set = new AnimatorSet();
set.playTogether(oa, oaContentAlpha);
set.setDuration(mExpandDuration);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mState = STATE_ANIMATING;
}
@Override
public void onAnimationEnd(Animator animation) {
mState = STATE_SMALL;
}
});
set.start();
}
public void animateClosed() {
if (!(getParent() instanceof CellLayoutChildren)) return;
CellLayoutChildren clc = (CellLayoutChildren) getParent();
final CellLayout cellLayout = (CellLayout) clc.getParent();
FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
oa.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
requestLayout();
}
});
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
AnimatorSet set = new AnimatorSet();
set.playTogether(oa, oaContentAlpha);
set.setDuration(mExpandDuration);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
cellLayout.removeViewWithoutMarkingCells(Folder.this);
mState = STATE_OPEN;
}
@Override
public void onAnimationStart(Animator animation) {
mState = STATE_ANIMATING;
}
});
set.start();
}
void notifyDataSetChanged() {
// recreate all the children if the data set changes under us. We may want to do this more
// intelligently (ie just removing the views that should no longer exist)
mContent.removeAllViewsInLayout();
bind(mInfo);
}
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
final int itemType = item.itemType;
return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
&& item.container != mInfo.id;
}
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
ShortcutInfo item;
if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
item = ((ApplicationInfo)dragInfo).makeShortcut();
item.spanX = 1;
item.spanY = 1;
} else {
item = (ShortcutInfo)dragInfo;
}
findAndSetEmptyCells(item);
mInfo.add(item);
createAndAddShortcut(item);
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
}
protected boolean findAndSetEmptyCells(ShortcutInfo item) {
int[] emptyCell = new int[2];
if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
item.cellX = emptyCell[0];
item.cellY = emptyCell[1];
LauncherModel.addOrMoveItemInDatabase(
mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
return true;
} else {
return false;
}
}
protected void createAndAddShortcut(ShortcutInfo item) {
final TextView textView =
(TextView) mInflater.inflate(R.layout.application_boxed, this, false);
textView.setCompoundDrawablesWithIntrinsicBounds(null,
new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
textView.setText(item.title);
textView.setTag(item);
textView.setOnClickListener(this);
textView.setOnLongClickListener(this);
CellLayout.LayoutParams lp =
new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
boolean insert = false;
mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
}
public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
public void onDropCompleted(View target, Object dragInfo, boolean success) {
if (success) {
mInfo.remove(mDragItem);
}
}
public boolean isDropEnabled() {
return true;
}
public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
return null;
}
}
+2 -2
View File
@@ -29,7 +29,7 @@ import com.android.launcher.R;
* An icon that can appear on in the workspace representing an {@link UserFolder}.
*/
public class FolderIcon extends BubbleTextView implements DropTarget {
private UserFolderInfo mInfo;
private FolderInfo mInfo;
private Launcher mLauncher;
private Drawable mCloseIcon;
private Drawable mOpenIcon;
@@ -50,7 +50,7 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
}
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
UserFolderInfo folderInfo, IconCache iconCache) {
FolderInfo folderInfo, IconCache iconCache) {
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
+37 -1
View File
@@ -16,12 +16,15 @@
package com.android.launcher2;
import java.util.ArrayList;
import android.content.ContentValues;
/**
* Represents a folder containing shortcuts or apps.
*/
class FolderInfo extends ItemInfo {
/**
* Whether this folder has been opened
*/
@@ -31,4 +34,37 @@ class FolderInfo extends ItemInfo {
* The folder name.
*/
CharSequence title;
/**
* The apps and shortcuts
*/
ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
FolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
}
/**
* Add an app or shortcut
*
* @param item
*/
public void add(ShortcutInfo item) {
contents.add(item);
}
/**
* Remove an app or shortcut. Does not change the DB.
*
* @param item
*/
public void remove(ShortcutInfo item) {
contents.remove(item);
}
@Override
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
values.put(LauncherSettings.Favorites.TITLE, title.toString());
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ class ItemInfo {
/**
* One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
* {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
* {@link LauncherSettings.Favorites#ITEM_TYPE_USER_FOLDER}, or
* {@link LauncherSettings.Favorites#ITEM_TYPE_FOLDER}, or
* {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}.
*/
int itemType;
+23 -170
View File
@@ -17,9 +17,13 @@
package com.android.launcher2;
import com.android.common.Search;
import com.android.launcher.R;
import com.android.launcher2.Workspace.ShrinkState;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -63,10 +67,8 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.LiveFolders;
import android.provider.Settings;
import android.speech.RecognizerIntent;
import android.text.Selection;
@@ -99,13 +101,9 @@ import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.android.common.Search;
import com.android.launcher.R;
import com.android.launcher2.Workspace.ShrinkState;
/**
* Default launcher application.
@@ -131,11 +129,9 @@ public final class Launcher extends Activity
private static final int MENU_SETTINGS = MENU_NOTIFICATIONS + 1;
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CREATE_LIVE_FOLDER = 4;
private static final int REQUEST_CREATE_APPWIDGET = 5;
private static final int REQUEST_PICK_APPLICATION = 6;
private static final int REQUEST_PICK_SHORTCUT = 7;
private static final int REQUEST_PICK_LIVE_FOLDER = 8;
private static final int REQUEST_PICK_APPWIDGET = 9;
private static final int REQUEST_PICK_WALLPAPER = 10;
@@ -154,7 +150,7 @@ public final class Launcher extends Activity
// Type: int
private static final String RUNTIME_STATE = "launcher.state";
// Type: long
private static final String RUNTIME_STATE_USER_FOLDERS = "launcher.user_folder";
private static final String RUNTIME_STATE_FOLDERS = "launcher.folder";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
// Type: int
@@ -636,12 +632,6 @@ public final class Launcher extends Activity
case REQUEST_CREATE_SHORTCUT:
completeAddShortcut(args.intent, args.screen, args.cellX, args.cellY);
break;
case REQUEST_PICK_LIVE_FOLDER:
addLiveFolder(args.intent);
break;
case REQUEST_CREATE_LIVE_FOLDER:
completeAddLiveFolder(args.intent, args.screen, args.cellX, args.cellY);
break;
case REQUEST_PICK_APPWIDGET:
addAppWidgetFromPick(args.intent);
break;
@@ -1471,7 +1461,7 @@ public final class Launcher extends Activity
final FolderInfo info = folders.get(i).getInfo();
ids[i] = info.id;
}
outState.putLongArray(RUNTIME_STATE_USER_FOLDERS, ids);
outState.putLongArray(RUNTIME_STATE_FOLDERS, ids);
} else {
super.onSaveInstanceState(outState);
}
@@ -1808,31 +1798,8 @@ public final class Launcher extends Activity
startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
}
void addLiveFolderFromDrop(ComponentName componentName, int screen, int[] position) {
resetAddInfo();
mAddScreen = screen;
mAddDropPosition = position;
Intent createFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
createFolderIntent.setComponent(componentName);
addLiveFolder(createFolderIntent);
}
void addLiveFolder(Intent intent) { // YYY add screen intersect etc. parameters here
// Handle case where user selected "Folder"
String folderName = getResources().getString(R.string.group_folder);
String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
if (folderName != null && folderName.equals(shortcutName)) {
addFolder(mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
} else {
startActivityForResultSafely(intent, REQUEST_CREATE_LIVE_FOLDER);
}
}
FolderIcon addFolder(int screen, int intersectCellX, int intersectCellY) {
UserFolderInfo folderInfo = new UserFolderInfo();
FolderInfo folderInfo = new FolderInfo();
folderInfo.title = getText(R.string.folder_name);
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
@@ -1860,67 +1827,6 @@ public final class Launcher extends Activity
sFolders.remove(folder.id);
}
private void completeAddLiveFolder(
Intent data, int screen, int intersectCellX, int intersectCellY) {
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
final int[] cellXY = mTmpAddItemCellCoordinates;
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
showOutOfSpaceMessage();
return;
}
final LiveFolderInfo info = addLiveFolder(this, data, screen, cellXY[0], cellXY[1], false);
if (!mRestoring) {
final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this,
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
}
}
static LiveFolderInfo addLiveFolder(Context context, Intent data,
int screen, int cellX, int cellY, boolean notify) {
Intent baseIntent = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT);
String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
Drawable icon = null;
Intent.ShortcutIconResource iconResource = null;
Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
if (extra != null && extra instanceof Intent.ShortcutIconResource) {
try {
iconResource = (Intent.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 live folder icon: " + extra);
}
}
if (icon == null) {
icon = context.getResources().getDrawable(R.drawable.ic_launcher_folder);
}
final LiveFolderInfo info = new LiveFolderInfo();
info.icon = Utilities.createIconBitmap(icon, context);
info.title = name;
info.iconResource = iconResource;
info.uri = data.getData();
info.baseIntent = baseIntent;
info.displayMode = data.getIntExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE,
LiveFolders.DISPLAY_MODE_GRID);
LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
screen, cellX, cellY, notify);
sFolders.put(info.id, info);
return info;
}
private void showNotifications() {
final StatusBarManager statusBar = (StatusBarManager) getSystemService(STATUS_BAR_SERVICE);
if (statusBar != null) {
@@ -2010,19 +1916,10 @@ public final class Launcher extends Activity
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
if (parent != null) {
CellLayout cl = (CellLayout) parent;
if (!(folder instanceof UserFolder)) {
// User folders will remove themselves
cl.removeViewWithoutMarkingCells(folder);
}
if (folder instanceof DropTarget) {
// Live folders aren't DropTargets.
mDragController.removeDropTarget((DropTarget)folder);
}
}
if (folder instanceof UserFolder) {
UserFolder uf = (UserFolder) folder;
uf.animateClosed();
mDragController.removeDropTarget((DropTarget)folder);
}
folder.animateClosed();
folder.onClose();
}
@@ -2221,15 +2118,7 @@ public final class Launcher extends Activity
* @param folderInfo The FolderInfo describing the folder to open.
*/
public void openFolder(FolderInfo folderInfo) {
Folder openFolder;
if (folderInfo instanceof UserFolderInfo) {
openFolder = UserFolder.fromXml(this);
} else if (folderInfo instanceof LiveFolderInfo) {
openFolder = com.android.launcher2.LiveFolder.fromXml(this, folderInfo);
} else {
return;
}
Folder openFolder = Folder.fromXml(this);
openFolder.setDragController(mDragController);
openFolder.setLauncher(this);
@@ -2238,10 +2127,7 @@ public final class Launcher extends Activity
folderInfo.opened = true;
mWorkspace.addInFullScreen(openFolder, folderInfo.screen);
if (openFolder instanceof UserFolder) {
UserFolder uf = (UserFolder) openFolder;
uf.animateOpen();
}
openFolder.animateOpen();
openFolder.onOpen();
}
@@ -3359,31 +3245,6 @@ public final class Launcher extends Activity
break;
}
case AddAdapter.ITEM_LIVE_FOLDER: {
// Insert extra item to handle inserting folder
Bundle bundle = new Bundle();
ArrayList<String> shortcutNames = new ArrayList<String>();
shortcutNames.add(res.getString(R.string.group_folder));
bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
ArrayList<ShortcutIconResource> shortcutIcons =
new ArrayList<ShortcutIconResource>();
shortcutIcons.add(ShortcutIconResource.fromContext(Launcher.this,
R.drawable.ic_launcher_folder));
bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
pickIntent.putExtra(Intent.EXTRA_INTENT,
new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER));
pickIntent.putExtra(Intent.EXTRA_TITLE,
getText(R.string.title_select_live_folder));
pickIntent.putExtras(bundle);
startActivityForResult(pickIntent, REQUEST_PICK_LIVE_FOLDER);
break;
}
case AddAdapter.ITEM_WALLPAPER: {
startWallpaper();
break;
@@ -3521,21 +3382,13 @@ public final class Launcher extends Activity
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(UserFolderInfo) item, mIconCache);
(FolderInfo) item, mIconCache);
workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(
R.layout.live_folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(LiveFolderInfo) item);
workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
}
}
@@ -3604,9 +3457,9 @@ public final class Launcher extends Activity
mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
}
final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
if (userFolders != null) {
for (long folderId : userFolders) {
final long[] folders = mSavedState.getLongArray(RUNTIME_STATE_FOLDERS);
if (folders != null) {
for (long folderId : folders) {
final FolderInfo info = sFolders.get(folderId);
if (info != null) {
openFolder(info);
+13 -116
View File
@@ -37,7 +37,6 @@ import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
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;
@@ -268,8 +267,7 @@ public class LauncherModel extends BroadcastReceiver {
Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
"_id=? and (itemType=? or itemType=?)",
new String[] { String.valueOf(id),
String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER),
String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null);
String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);
try {
if (c.moveToFirst()) {
@@ -282,11 +280,8 @@ public class LauncherModel extends BroadcastReceiver {
FolderInfo folderInfo = null;
switch (c.getInt(itemTypeIndex)) {
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
folderInfo = findOrMakeUserFolder(folderList, id);
break;
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
folderInfo = findOrMakeLiveFolder(folderList, id);
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
folderInfo = findOrMakeFolder(folderList, id);
break;
}
@@ -388,7 +383,7 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Remove the contents of the specified folder from the database
*/
static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) {
static void deleteFolderContentsFromDatabase(Context context, FolderInfo info) {
final ContentResolver cr = context.getContentResolver();
cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
@@ -841,8 +836,8 @@ public class LauncherModel extends BroadcastReceiver {
break;
default:
// Item is in a user folder
UserFolderInfo folderInfo =
findOrMakeUserFolder(mFolders, container);
FolderInfo folderInfo =
findOrMakeFolder(mFolders, container);
folderInfo.add(info);
break;
}
@@ -862,9 +857,9 @@ public class LauncherModel extends BroadcastReceiver {
}
break;
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
id = c.getLong(idIndex);
UserFolderInfo folderInfo = findOrMakeUserFolder(mFolders, id);
FolderInfo folderInfo = findOrMakeFolder(mFolders, id);
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
@@ -887,57 +882,6 @@ public class LauncherModel extends BroadcastReceiver {
mFolders.put(folderInfo.id, folderInfo);
break;
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
id = c.getLong(idIndex);
Uri uri = Uri.parse(c.getString(uriIndex));
// 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);
// check & update map of what's occupied
if (!checkItemPlacement(occupied, liveFolderInfo)) {
break;
}
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_APPWIDGET:
// Read all Launcher-specific widget details
int appWidgetId = c.getInt(appWidgetIdIndex);
@@ -1667,38 +1611,6 @@ public class LauncherModel extends BroadcastReceiver {
return info;
}
private void loadLiveFolderIcon(Context context, Cursor c, int iconTypeIndex,
int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
int iconType = c.getInt(iconTypeIndex);
switch (iconType) {
case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
String packageName = c.getString(iconPackageIndex);
String resourceName = c.getString(iconResourceIndex);
PackageManager packageManager = context.getPackageManager();
try {
Resources appResources = packageManager.getResourcesForApplication(packageName);
final int id = appResources.getIdentifier(resourceName, null, null);
liveFolderInfo.icon = Utilities.createIconBitmap(
mIconCache.getFullResIcon(appResources, id), context);
} catch (Exception e) {
Resources resources = context.getResources();
liveFolderInfo.icon = Utilities.createIconBitmap(
mIconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder),
context);
}
liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
liveFolderInfo.iconResource.packageName = packageName;
liveFolderInfo.iconResource.resourceName = resourceName;
break;
default:
Resources resources = context.getResources();
liveFolderInfo.icon = Utilities.createIconBitmap(
mIconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder),
context);
}
}
void updateSavedIcon(Context context, ShortcutInfo info, Cursor c, int iconIndex) {
// If apps can't be on SD, don't even bother.
if (!mAppsCanBeOnExternalStorage) {
@@ -1734,33 +1646,18 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
* Return an existing UserFolderInfo object if we have encountered this ID previously,
* Return an existing FolderInfo object if we have encountered this ID previously,
* or make a new one.
*/
private static UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) {
private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {
// See if a placeholder was created for us already
FolderInfo folderInfo = folders.get(id);
if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) {
if (folderInfo == null) {
// No placeholder -- create a new instance
folderInfo = new UserFolderInfo();
folderInfo = new FolderInfo();
folders.put(id, folderInfo);
}
return (UserFolderInfo) folderInfo;
}
/**
* Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
* new one.
*/
private static LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) {
// See if a placeholder was created for us already
FolderInfo folderInfo = folders.get(id);
if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) {
// No placeholder -- create a new instance
folderInfo = new LiveFolderInfo();
folders.put(id, folderInfo);
}
return (LiveFolderInfo) folderInfo;
return folderInfo;
}
private static String getLabel(PackageManager manager, ActivityInfo activityInfo) {
@@ -16,8 +16,8 @@
package com.android.launcher2;
import android.provider.BaseColumns;
import android.net.Uri;
import android.provider.BaseColumns;
/**
* Settings related utilities.
@@ -169,11 +169,15 @@ class LauncherSettings {
/**
* The favorite is a user created folder
*/
static final int ITEM_TYPE_USER_FOLDER = 2;
static final int ITEM_TYPE_FOLDER = 2;
/**
* The favorite is a live folder
*/
* The favorite is a live folder
*
* Note: live folders can no longer be added to Launcher, and any live folders which
* exist within the launcher database will be ignored when loading. That said, these
* entries in the database may still exist, and are not automatically stripped.
*/
static final int ITEM_TYPE_LIVE_FOLDER = 3;
/**
-167
View File
@@ -1,167 +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.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.net.Uri;
import android.provider.LiveFolders;
import android.os.AsyncTask;
import android.database.Cursor;
import android.widget.GridView;
import java.lang.ref.WeakReference;
import com.android.launcher.R;
public class LiveFolder extends Folder {
private AsyncTask<LiveFolderInfo,Void,Cursor> mLoadingTask;
protected GridView mContent;
public LiveFolder(Context context, AttributeSet attrs) {
super(context, attrs);
}
static LiveFolder fromXml(Context context, FolderInfo folderInfo) {
final int layout = isDisplayModeList(folderInfo) ?
R.layout.live_folder_list : R.layout.live_folder_grid;
return (LiveFolder) LayoutInflater.from(context).inflate(layout, null);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mContent = (GridView) findViewById(R.id.folder_content);
mContent.setOnItemClickListener(this);
mContent.setOnItemLongClickListener(this);
}
private static boolean isDisplayModeList(FolderInfo folderInfo) {
return ((LiveFolderInfo) folderInfo).displayMode ==
LiveFolders.DISPLAY_MODE_LIST;
}
@Override
public void onItemClick(AdapterView parent, View v, int position, long id) {
LiveFolderAdapter.ViewHolder holder = (LiveFolderAdapter.ViewHolder) v.getTag();
if (holder.useBaseIntent) {
final Intent baseIntent = ((LiveFolderInfo) mInfo).baseIntent;
if (baseIntent != null) {
final Intent intent = new Intent(baseIntent);
Uri uri = baseIntent.getData();
uri = uri.buildUpon().appendPath(Long.toString(holder.id)).build();
intent.setData(uri);
mLauncher.startActivitySafely(intent, "(position=" + position + ", id=" + id + ")");
}
} else if (holder.intent != null) {
mLauncher.startActivitySafely(holder.intent,
"(position=" + position + ", id=" + id + ")");
}
}
/**
* Sets the adapter used to populate the content area. The adapter must only
* contains ShortcutInfo items.
*
* @param adapter The list of applications to display in the folder.
*/
void setContentAdapter(BaseAdapter adapter) {
mContent.setAdapter(adapter);
}
@Override
void notifyDataSetChanged() {
((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
return false;
}
void bind(FolderInfo info) {
super.bind(info);
if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
mLoadingTask.cancel(true);
}
mLoadingTask = new FolderLoadingTask(this).execute((LiveFolderInfo) info);
}
@Override
void onOpen() {
super.onOpen();
// When the folder opens, we need to refresh the GridView's selection by
// forcing a layout
mContent.requestLayout();
requestFocus();
}
@Override
void onClose() {
super.onClose();
if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
mLoadingTask.cancel(true);
}
// The adapter can be null if onClose() is called before FolderLoadingTask
// is done querying the provider
final LiveFolderAdapter adapter = (LiveFolderAdapter) mContent.getAdapter();
if (adapter != null) {
adapter.cleanup();
}
}
static class FolderLoadingTask extends AsyncTask<LiveFolderInfo, Void, Cursor> {
private final WeakReference<LiveFolder> mFolder;
private LiveFolderInfo mInfo;
FolderLoadingTask(LiveFolder folder) {
mFolder = new WeakReference<LiveFolder>(folder);
}
protected Cursor doInBackground(LiveFolderInfo... params) {
final LiveFolder folder = mFolder.get();
if (folder != null) {
mInfo = params[0];
return LiveFolderAdapter.query(folder.mLauncher, mInfo);
}
return null;
}
@Override
protected void onPostExecute(Cursor cursor) {
if (!isCancelled()) {
if (cursor != null) {
final LiveFolder folder = mFolder.get();
if (folder != null) {
final Launcher launcher = folder.mLauncher;
folder.setContentAdapter(new LiveFolderAdapter(launcher, mInfo, cursor));
}
}
} else if (cursor != null) {
cursor.close();
}
}
}
}
@@ -1,217 +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.widget.CursorAdapter;
import android.widget.TextView;
import android.widget.ImageView;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.pm.PackageManager;
import android.view.View;
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.database.Cursor;
import android.provider.LiveFolders;
import android.graphics.drawable.Drawable;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.lang.ref.SoftReference;
import com.android.launcher.R;
class LiveFolderAdapter extends CursorAdapter {
private boolean mIsList;
private LayoutInflater mInflater;
private final HashMap<String, Drawable> mIcons = new HashMap<String, Drawable>();
private final HashMap<Long, SoftReference<Drawable>> mCustomIcons =
new HashMap<Long, SoftReference<Drawable>>();
private final Launcher mLauncher;
LiveFolderAdapter(Launcher launcher, LiveFolderInfo info, Cursor cursor) {
super(launcher, cursor, true);
mIsList = info.displayMode == LiveFolders.DISPLAY_MODE_LIST;
mInflater = LayoutInflater.from(launcher);
mLauncher = launcher;
mLauncher.startManagingCursor(getCursor());
}
static Cursor query(Context context, LiveFolderInfo info) {
return context.getContentResolver().query(info.uri, null, null,
null, LiveFolders.NAME + " ASC");
}
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view;
final ViewHolder holder = new ViewHolder();
if (!mIsList) {
view = mInflater.inflate(R.layout.application_boxed, parent, false);
} else {
view = mInflater.inflate(R.layout.application_list, parent, false);
holder.description = (TextView) view.findViewById(R.id.description);
holder.icon = (ImageView) view.findViewById(R.id.icon);
}
holder.name = (TextView) view.findViewById(R.id.name);
holder.idIndex = cursor.getColumnIndexOrThrow(LiveFolders._ID);
holder.nameIndex = cursor.getColumnIndexOrThrow(LiveFolders.NAME);
holder.descriptionIndex = cursor.getColumnIndex(LiveFolders.DESCRIPTION);
holder.intentIndex = cursor.getColumnIndex(LiveFolders.INTENT);
holder.iconBitmapIndex = cursor.getColumnIndex(LiveFolders.ICON_BITMAP);
holder.iconResourceIndex = cursor.getColumnIndex(LiveFolders.ICON_RESOURCE);
holder.iconPackageIndex = cursor.getColumnIndex(LiveFolders.ICON_PACKAGE);
view.setTag(holder);
return view;
}
public void bindView(View view, Context context, Cursor cursor) {
final ViewHolder holder = (ViewHolder) view.getTag();
holder.id = cursor.getLong(holder.idIndex);
final Drawable icon = loadIcon(context, cursor, holder);
holder.name.setText(cursor.getString(holder.nameIndex));
if (!mIsList) {
holder.name.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null);
} else {
final boolean hasIcon = icon != null;
holder.icon.setVisibility(hasIcon ? View.VISIBLE : View.GONE);
if (hasIcon) holder.icon.setImageDrawable(icon);
if (holder.descriptionIndex != -1) {
final String description = cursor.getString(holder.descriptionIndex);
if (description != null) {
holder.description.setText(description);
holder.description.setVisibility(View.VISIBLE);
} else {
holder.description.setVisibility(View.GONE);
}
} else {
holder.description.setVisibility(View.GONE);
}
}
if (holder.intentIndex != -1) {
try {
holder.intent = Intent.parseUri(cursor.getString(holder.intentIndex), 0);
} catch (URISyntaxException e) {
// Ignore
}
} else {
holder.useBaseIntent = true;
}
}
private Drawable loadIcon(Context context, Cursor cursor, ViewHolder holder) {
Drawable icon = null;
byte[] data = null;
if (holder.iconBitmapIndex != -1) {
data = cursor.getBlob(holder.iconBitmapIndex);
}
if (data != null) {
final SoftReference<Drawable> reference = mCustomIcons.get(holder.id);
if (reference != null) {
icon = reference.get();
}
if (icon == null) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
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) {
final String resource = cursor.getString(holder.iconResourceIndex);
icon = mIcons.get(resource);
if (icon == null) {
try {
final PackageManager packageManager = context.getPackageManager();
Resources resources = packageManager.getResourcesForApplication(
cursor.getString(holder.iconPackageIndex));
final int id = resources.getIdentifier(resource,
null, null);
icon = new FastBitmapDrawable(
Utilities.createIconBitmap(resources.getDrawable(id), mContext));
mIcons.put(resource, icon);
} catch (Exception e) {
// Ignore
}
}
}
return icon;
}
void cleanup() {
for (Drawable icon : mIcons.values()) {
icon.setCallback(null);
}
mIcons.clear();
for (SoftReference<Drawable> icon : mCustomIcons.values()) {
final Drawable drawable = icon.get();
if (drawable != null) {
drawable.setCallback(null);
}
}
mCustomIcons.clear();
final Cursor cursor = getCursor();
if (cursor != null) {
try {
cursor.close();
} finally {
mLauncher.stopManagingCursor(cursor);
}
}
}
static class ViewHolder {
TextView name;
TextView description;
ImageView icon;
Intent intent;
long id;
boolean useBaseIntent;
int idIndex;
int nameIndex;
int descriptionIndex = -1;
int intentIndex = -1;
int iconBitmapIndex = -1;
int iconResourceIndex = -1;
int iconPackageIndex = -1;
}
}
@@ -1,82 +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.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.graphics.Bitmap;
import com.android.launcher.R;
public class LiveFolderIcon extends FolderIcon {
public LiveFolderIcon(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LiveFolderIcon(Context context) {
super(context);
}
static LiveFolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
LiveFolderInfo folderInfo) {
LiveFolderIcon icon = (LiveFolderIcon)
LayoutInflater.from(launcher).inflate(resId, group, false);
final Resources resources = launcher.getResources();
Bitmap b = folderInfo.icon;
if (b == null) {
b = Utilities.createIconBitmap(resources.getDrawable(R.drawable.ic_launcher_folder),
launcher);
}
icon.setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(b), null, null);
icon.setText(folderInfo.title);
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
return icon;
}
@Override
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
return false;
}
@Override
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
@Override
public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
@Override
public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
@Override
public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
}
@@ -1,70 +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.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
class LiveFolderInfo extends FolderInfo {
/**
* The base intent, if it exists.
*/
Intent baseIntent;
/**
* The live folder's content uri.
*/
Uri uri;
/**
* The live folder's display type.
*/
int displayMode;
/**
* The live folder icon.
*/
Bitmap icon;
/**
* Reference to the live folder icon as an application's resource.
*/
Intent.ShortcutIconResource iconResource;
LiveFolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER;
}
@Override
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
values.put(LauncherSettings.Favorites.TITLE, title.toString());
values.put(LauncherSettings.Favorites.URI, uri.toString());
if (baseIntent != null) {
values.put(LauncherSettings.Favorites.INTENT, baseIntent.toUri(0));
}
values.put(LauncherSettings.Favorites.ICON_TYPE, LauncherSettings.Favorites.ICON_TYPE_RESOURCE);
values.put(LauncherSettings.Favorites.DISPLAY_MODE, displayMode);
if (iconResource != null) {
values.put(LauncherSettings.Favorites.ICON_PACKAGE, iconResource.packageName);
values.put(LauncherSettings.Favorites.ICON_RESOURCE, iconResource.resourceName);
}
}
}
-326
View File
@@ -1,326 +0,0 @@
package com.android.launcher2;
import java.util.ArrayList;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.android.launcher.R;
/**
* Folder which contains applications or shortcuts chosen by the user.
*
*/
public class UserFolder extends Folder implements DropTarget {
private static final String TAG = "Launcher.UserFolder";
static final int STATE_NONE = -1;
static final int STATE_SMALL = 0;
static final int STATE_ANIMATING = 1;
static final int STATE_OPEN = 2;
private int mExpandDuration;
protected CellLayout mContent;
private final LayoutInflater mInflater;
private final IconCache mIconCache;
private int mState = STATE_NONE;
public UserFolder(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mContent = (CellLayout) findViewById(R.id.folder_content);
}
/**
* Creates a new UserFolder, inflated from R.layout.user_folder.
*
* @param context The application's context.
*
* @return A new UserFolder.
*/
static UserFolder fromXml(Context context) {
return (UserFolder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
}
/**
* This method is intended to make the UserFolder to be visually identical in size and position
* to its associated FolderIcon. This allows for a seamless transition into the expanded state.
*/
private void positionAndSizeAsIcon() {
if (!(getParent() instanceof CellLayoutChildren)) return;
CellLayoutChildren clc = (CellLayoutChildren) getParent();
CellLayout cellLayout = (CellLayout) clc.getParent();
FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
lp.width = iconLp.width;
lp.height = iconLp.height;
lp.x = iconLp.x;
lp.y = iconLp.y;
mContent.setAlpha(0f);
mState = STATE_SMALL;
}
public void animateOpen() {
if (mState != STATE_SMALL) {
positionAndSizeAsIcon();
}
if (!(getParent() instanceof CellLayoutChildren)) return;
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
CellLayoutChildren clc = (CellLayoutChildren) getParent();
CellLayout cellLayout = (CellLayout) clc.getParent();
Rect r = cellLayout.getContentRect(null);
PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", r.width());
PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", r.height());
PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", 0);
PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", 0);
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
oa.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
requestLayout();
}
});
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
AnimatorSet set = new AnimatorSet();
set.playTogether(oa, oaContentAlpha);
set.setDuration(mExpandDuration);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mState = STATE_ANIMATING;
}
@Override
public void onAnimationEnd(Animator animation) {
mState = STATE_SMALL;
}
});
set.start();
}
public void animateClosed() {
if (!(getParent() instanceof CellLayoutChildren)) return;
CellLayoutChildren clc = (CellLayoutChildren) getParent();
final CellLayout cellLayout = (CellLayout) clc.getParent();
FolderIcon fi = (FolderIcon) cellLayout.getChildAt(mInfo.cellX, mInfo.cellY);
CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) fi.getLayoutParams();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
oa.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
requestLayout();
}
});
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
ObjectAnimator oaContentAlpha = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
AnimatorSet set = new AnimatorSet();
set.playTogether(oa, oaContentAlpha);
set.setDuration(mExpandDuration);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
cellLayout.removeViewWithoutMarkingCells(UserFolder.this);
mState = STATE_OPEN;
}
@Override
public void onAnimationStart(Animator animation) {
mState = STATE_ANIMATING;
}
});
set.start();
}
@Override
void notifyDataSetChanged() {
// recreate all the children if the data set changes under us. We may want to do this more
// intelligently (ie just removing the views that should no longer exist)
mContent.removeAllViewsInLayout();
bind(mInfo);
}
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// refactor this code from Folder
ShortcutInfo item = (ShortcutInfo) tag;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
item.intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
mLauncher.startActivitySafely(item.intent, item);
} else {
super.onClick(v);
}
}
public boolean onLongClick(View v) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// refactor this code from Folder
ShortcutInfo item = (ShortcutInfo) tag;
if (!v.isInTouchMode()) {
return false;
}
mLauncher.getWorkspace().onDragStartedWithItem(v);
mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
mLauncher.closeFolder(this);
mDragItem = item;
return true;
} else {
return super.onLongClick(v);
}
}
public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
final int itemType = item.itemType;
return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
&& item.container != mInfo.id;
}
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
ShortcutInfo item;
if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
item = ((ApplicationInfo)dragInfo).makeShortcut();
item.spanX = 1;
item.spanY = 1;
} else {
item = (ShortcutInfo)dragInfo;
}
findAndSetEmptyCells(item);
((UserFolderInfo)mInfo).add(item);
createAndAddShortcut(item);
LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
}
protected boolean findAndSetEmptyCells(ShortcutInfo item) {
int[] emptyCell = new int[2];
if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
item.cellX = emptyCell[0];
item.cellY = emptyCell[1];
LauncherModel.addOrMoveItemInDatabase(
mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
return true;
} else {
return false;
}
}
protected void createAndAddShortcut(ShortcutInfo item) {
final TextView textView =
(TextView) mInflater.inflate(R.layout.application_boxed, this, false);
textView.setCompoundDrawablesWithIntrinsicBounds(null,
new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
textView.setText(item.title);
textView.setTag(item);
textView.setOnClickListener(this);
textView.setOnLongClickListener(this);
CellLayout.LayoutParams lp =
new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
boolean insert = false;
mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
}
public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
}
@Override
public void onDropCompleted(View target, Object dragInfo, boolean success) {
if (success) {
((UserFolderInfo)mInfo).remove(mDragItem);
}
}
public boolean isDropEnabled() {
return true;
}
void bind(FolderInfo info) {
super.bind(info);
ArrayList<ShortcutInfo> children = ((UserFolderInfo)info).contents;
for (int i = 0; i < children.size(); i++) {
ShortcutInfo child = (ShortcutInfo) children.get(i);
if ((child.cellX == -1 && child.cellY == -1) ||
mContent.isOccupied(child.cellX, child.cellY)) {
findAndSetEmptyCells(child);
}
createAndAddShortcut((ShortcutInfo) children.get(i));
}
}
@Override
void onOpen() {
super.onOpen();
// When the folder opens, we need to refresh the GridView's selection by
// forcing a layout
// TODO: find out if this is still necessary
mContent.requestLayout();
requestFocus();
}
@Override
public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
DragView dragView, Object dragInfo) {
return null;
}
}
@@ -1,59 +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.ContentValues;
import java.util.ArrayList;
/**
* Represents a folder containing shortcuts or apps.
*/
class UserFolderInfo extends FolderInfo {
/**
* The apps and shortcuts
*/
ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
UserFolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER;
}
/**
* Add an app or shortcut
*
* @param item
*/
public void add(ShortcutInfo item) {
contents.add(item);
}
/**
* Remove an app or shortcut. Does not change the DB.
*
* @param item
*/
public void remove(ShortcutInfo item) {
contents.remove(item);
}
@Override
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
values.put(LauncherSettings.Favorites.TITLE, title.toString());
}
}
+4 -23
View File
@@ -38,7 +38,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -50,7 +49,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.IBinder;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -3030,9 +3028,6 @@ public class Workspace extends SmoothPagedView
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
break;
case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
break;
@@ -3055,9 +3050,9 @@ public class Workspace extends SmoothPagedView
view = mLauncher.createShortcut(R.layout.application, cellLayout,
(ShortcutInfo) info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
cellLayout, (UserFolderInfo) info, mIconCache);
cellLayout, (FolderInfo) info, mIconCache);
break;
default:
throw new IllegalStateException("Unknown item type: " + info.itemType);
@@ -3345,8 +3340,8 @@ public class Workspace extends SmoothPagedView
}
}
}
} else if (tag instanceof UserFolderInfo) {
final UserFolderInfo info = (UserFolderInfo) tag;
} else if (tag instanceof FolderInfo) {
final FolderInfo info = (FolderInfo) tag;
final ArrayList<ShortcutInfo> contents = info.contents;
final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
final int contentsCount = contents.size();
@@ -3374,20 +3369,6 @@ public class Workspace extends SmoothPagedView
if (folder != null)
folder.notifyDataSetChanged();
}
} else if (tag instanceof LiveFolderInfo) {
final LiveFolderInfo info = (LiveFolderInfo) tag;
final Uri uri = info.uri;
final ProviderInfo providerInfo = manager.resolveContentProvider(
uri.getAuthority(), 0);
if (providerInfo != null) {
for (String packageName: packageNames) {
if (packageName.equals(providerInfo.packageName)) {
LauncherModel.deleteItemFromDatabase(mLauncher, info);
childrenToRemove.add(view);
}
}
}
} else if (tag instanceof LauncherAppWidgetInfo) {
final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
final AppWidgetProviderInfo provider =