summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanesh Mondegarian <daneshm90@gmail.com>2013-09-10 06:14:16 +0000
committerGerrit Code Review <gerrit@cyanogenmod.org>2013-09-10 06:14:16 +0000
commit1b2a90776d8414d236bda2ecdf94ff8f58217313 (patch)
treeccec2777c71ddb5ced1919044956eaf15acb74c7
parent0e0db4378ce5f40b931be9368a7a56d6109f47df (diff)
parente576f6e7887b063d1b6d9a2052eedd4cc7c014ee (diff)
downloadandroid_packages_apps_Trebuchet-1b2a90776d8414d236bda2ecdf94ff8f58217313.tar.gz
android_packages_apps_Trebuchet-1b2a90776d8414d236bda2ecdf94ff8f58217313.tar.bz2
android_packages_apps_Trebuchet-1b2a90776d8414d236bda2ecdf94ff8f58217313.zip
Merge "Trebuchet : Support for custom icons per shortcut" into cm-10.2
-rw-r--r--AndroidManifest.xml6
-rw-r--r--res/layout/dialog_edit.xml1
-rw-r--r--res/values/cm_strings.xml2
-rw-r--r--src/com/cyanogenmod/trebuchet/BubbleTextView.java13
-rw-r--r--src/com/cyanogenmod/trebuchet/Folder.java20
-rw-r--r--src/com/cyanogenmod/trebuchet/IconCache.java15
-rw-r--r--src/com/cyanogenmod/trebuchet/IconPackHelper.java201
-rw-r--r--src/com/cyanogenmod/trebuchet/IconPickerActivity.java151
-rw-r--r--src/com/cyanogenmod/trebuchet/Launcher.java95
-rw-r--r--src/com/cyanogenmod/trebuchet/LauncherModel.java57
-rw-r--r--src/com/cyanogenmod/trebuchet/LauncherProvider.java9
-rw-r--r--src/com/cyanogenmod/trebuchet/LauncherSettings.java2
-rw-r--r--src/com/cyanogenmod/trebuchet/ShortcutInfo.java19
-rw-r--r--src/com/cyanogenmod/trebuchet/preference/Preferences.java2
14 files changed, 498 insertions, 95 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cd790fea1..d10cd801d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -132,6 +132,12 @@
<activity android:name="com.cyanogenmod.trebuchet.preference.HiddenAppsActivity"
android:label="@string/hidden_apps_title" />
+ <activity android:name=".IconPickerActivity"
+ android:exported="false"
+ android:excludeFromRecents="true"
+ android:noHistory="true"
+ android:launchMode="singleTop" />
+
<!-- Intent received used to install shortcuts from other applications -->
<receiver
android:name="com.cyanogenmod.trebuchet.InstallShortcutReceiver"
diff --git a/res/layout/dialog_edit.xml b/res/layout/dialog_edit.xml
index 40dfd62cd..a72900fc6 100644
--- a/res/layout/dialog_edit.xml
+++ b/res/layout/dialog_edit.xml
@@ -9,7 +9,6 @@
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageButton
- android:padding="5dp"
android:layout_width="@android:dimen/app_icon_size"
style="?android:attr/borderlessButtonStyle"
android:id="@+id/dialog_edit_icon"
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 8201f4c51..07eb2a5fc 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -165,7 +165,7 @@
<string name="preferences_interface_general_iconpack_title">Icon pack</string>
<string name="preferences_interface_general_iconpack_summary">Icon packs replace the default application icon</string>
<string name="dialog_pick_iconpack_title">Pick icon pack</string>
- <string name="default_iconpack_title">Default icons</string>
+ <string name="default_iconpack_title">Default</string>
<string name="no_iconpacks_summary">No icon packs installed</string>
<!-- Effects -->
diff --git a/src/com/cyanogenmod/trebuchet/BubbleTextView.java b/src/com/cyanogenmod/trebuchet/BubbleTextView.java
index 8a48b1645..511e63150 100644
--- a/src/com/cyanogenmod/trebuchet/BubbleTextView.java
+++ b/src/com/cyanogenmod/trebuchet/BubbleTextView.java
@@ -162,14 +162,21 @@ public class BubbleTextView extends TextView implements ShortcutInfo.ShortcutLis
}
@Override
- public void onTitleChanged(CharSequence title) {
+ public void onTitleChanged(ShortcutInfo item) {
if (mTextVisible) {
- setText(title);
+ setText(item.title);
} else {
- mVisibleText = title;
+ mVisibleText = item.title;
}
}
+ @Override
+ public void onIconChanged(ShortcutInfo item) {
+ setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(item.getIcon(null)),
+ null, null);
+ }
+
/**
* Draw this BubbleTextView into the given Canvas.
*
diff --git a/src/com/cyanogenmod/trebuchet/Folder.java b/src/com/cyanogenmod/trebuchet/Folder.java
index 6d3a2f64d..0b8410c40 100644
--- a/src/com/cyanogenmod/trebuchet/Folder.java
+++ b/src/com/cyanogenmod/trebuchet/Folder.java
@@ -22,6 +22,7 @@ import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -47,6 +48,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.cyanogenmod.trebuchet.FolderInfo.FolderListener;
+import com.cyanogenmod.trebuchet.ShortcutInfo.ShortcutListener;
import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
import java.util.ArrayList;
@@ -58,7 +60,7 @@ import java.util.Comparator;
*/
public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
- View.OnFocusChangeListener {
+ View.OnFocusChangeListener, ShortcutListener {
private static final String TAG = "Trebuchet.Folder";
protected DragController mDragController;
@@ -1128,6 +1130,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
findAndSetEmptyCells(item);
}
createAndAddShortcut(item);
+ item.setListener(this);
if (!(item instanceof LiveFolderItemInfo)) {
LauncherModel.addOrMoveItemInDatabase(
mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
@@ -1209,4 +1212,19 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
startEditingFolderName();
}
}
+
+ @Override
+ public void onTitleChanged(ShortcutInfo item) {
+ TextView textView = (TextView) getViewForInfo(item);
+ textView.setText(item.title);
+ }
+
+ @Override
+ public void onIconChanged(ShortcutInfo item) {
+ TextView textView = (TextView) getViewForInfo(item);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
+ mInfo.itemsChanged();
+ }
+
}
diff --git a/src/com/cyanogenmod/trebuchet/IconCache.java b/src/com/cyanogenmod/trebuchet/IconCache.java
index 7f4b13594..204c29780 100644
--- a/src/com/cyanogenmod/trebuchet/IconCache.java
+++ b/src/com/cyanogenmod/trebuchet/IconCache.java
@@ -109,7 +109,13 @@ public class IconCache {
}
public Drawable getFullResIcon(ActivityInfo info) {
-
+ int iconId = 0;
+ if (mIconPackHelper != null && mIconPackHelper.isIconPackLoaded()) {
+ iconId = mIconPackHelper.getResourceIdForActivityIcon(info);
+ if (iconId != 0) {
+ return getFullResIcon(mIconPackHelper.getIconPackResources(), iconId);
+ }
+ }
Resources resources;
try {
resources = mPackageManager.getResourcesForApplication(
@@ -118,13 +124,6 @@ public class IconCache {
resources = null;
}
if (resources != null) {
- int iconId = 0;
- if (mIconPackHelper != null && mIconPackHelper.isIconPackLoaded()) {
- iconId = mIconPackHelper.getResourceIdForActivityIcon(info);
- if (iconId != 0) {
- return getFullResIcon(mIconPackHelper.getIconPackResources(), iconId);
- }
- }
iconId = info.getIconResource();
if (iconId != 0) {
return getFullResIcon(resources, iconId);
diff --git a/src/com/cyanogenmod/trebuchet/IconPackHelper.java b/src/com/cyanogenmod/trebuchet/IconPackHelper.java
index 228ea2c88..ed44c250e 100644
--- a/src/com/cyanogenmod/trebuchet/IconPackHelper.java
+++ b/src/com/cyanogenmod/trebuchet/IconPackHelper.java
@@ -2,6 +2,7 @@ package com.cyanogenmod.trebuchet;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -10,6 +11,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
+import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
@@ -68,9 +70,9 @@ public class IconPackHelper {
return packages;
}
- private void loadResourcesFromXmlParser(XmlPullParser parser) throws XmlPullParserException, IOException {
+ private static void loadResourcesFromXmlParser(XmlPullParser parser,
+ Map<ComponentName, String> iconPackResources) throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
- mIconPackResources.clear();
do {
if (eventType != XmlPullParser.START_TAG) {
@@ -107,33 +109,89 @@ public class IconPackHelper {
}
if (name != null) {
- mIconPackResources.put(name, drawable);
+ iconPackResources.put(name, drawable);
}
} while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT);
}
- public void loadIconPack(String packageName) {
- String defaultIcons = mContext.getResources().getString(R.string.default_iconpack_title);
- if (packageName.equals(defaultIcons)) {
+ private static void loadApplicationResources(Context context,
+ Map<ComponentName, String> iconPackResources, String packageName) {
+ Field[] drawableItems = null;
+ try {
+ Context appContext = context.createPackageContext(packageName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ drawableItems = Class.forName(packageName+".R$drawable",
+ true, appContext.getClassLoader()).getFields();
+ } catch (Exception e){
return;
}
+ for (Field f : drawableItems) {
+ String name = f.getName();
+
+ String icon = name;
+ name = name.replaceAll("_", ".");
+
+ ComponentName compName = new ComponentName(name.toLowerCase(), "");
+ iconPackResources.put(compName, icon);
+
+ int activityIndex = name.lastIndexOf(".");
+ if (activityIndex <= 0 || activityIndex == name.length() - 1) {
+ continue;
+ }
+
+ String iconPackage = name.substring(0, activityIndex);
+ if (TextUtils.isEmpty(iconPackage)) {
+ continue;
+ }
+
+ String iconActivity = name.substring(activityIndex + 1);
+ if (TextUtils.isEmpty(iconActivity)) {
+ continue;
+ }
+
+ // Store entries as lower case to ensure match
+ iconPackage = iconPackage.toLowerCase();
+ iconActivity = iconActivity.toLowerCase();
+
+ iconActivity = iconPackage + "." + iconActivity;
+ compName = new ComponentName(iconPackage, iconActivity);
+ iconPackResources.put(compName, icon);
+ }
+ }
+
+ public void loadIconPack(String packageName) {
+ mIconPackResources = getIconPackResources(mContext, packageName);
Resources res = null;
try {
res = mContext.getPackageManager().getResourcesForApplication(packageName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
- return;
+ }
+ mLoadedIconPackResource = res;
+ mLoadedIconPackName = packageName;
+ }
+
+ public static Map<ComponentName, String> getIconPackResources(Context context, String packageName) {
+ String defaultIcons = context.getResources().getString(R.string.default_iconpack_title);
+ if (packageName.equals(defaultIcons)) {
+ return null;
+ }
+
+ Resources res = null;
+ try {
+ res = context.getPackageManager().getResourcesForApplication(packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
}
XmlPullParser parser = null;
InputStream inputStream = null;
+ Map<ComponentName, String> iconPackResources = new HashMap<ComponentName, String>();
try {
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- inputStream = res.getAssets().open("appfilter.xml");
- parser = factory.newPullParser();
- parser.setInput(inputStream, "UTF-8");
+ parser = res.getAssets().openXmlResourceParser("appfilter.xml");
} catch (Exception e) {
// Catch any exception since we want to fall back to parsing the xml/
// resource in all cases
@@ -145,10 +203,8 @@ public class IconPackHelper {
if (parser != null) {
try {
- loadResourcesFromXmlParser(parser);
- mLoadedIconPackResource = res;
- mLoadedIconPackName = packageName;
- return;
+ loadResourcesFromXmlParser(parser, iconPackResources);
+ return iconPackResources;
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
@@ -170,56 +226,60 @@ public class IconPackHelper {
int arrayId = res.getIdentifier("theme_iconpack", "array", packageName);
if (arrayId == 0) {
arrayId = res.getIdentifier("icon_pack", "array", packageName);
- if (arrayId == 0) {
- return;
- }
}
- String[] iconPack = res.getStringArray(arrayId);
- ComponentName compName = null;
- mIconPackResources.clear();
- for (String entry : iconPack) {
+ if (arrayId != 0) {
+ String[] iconPack = res.getStringArray(arrayId);
+ ComponentName compName = null;
+ for (String entry : iconPack) {
- if (TextUtils.isEmpty(entry)) {
- continue;
- }
+ if (TextUtils.isEmpty(entry)) {
+ continue;
+ }
- String icon = entry;
- entry = entry.replaceAll("_", ".");
+ String icon = entry;
+ entry = entry.replaceAll("_", ".");
- compName = new ComponentName(entry.toLowerCase(), "");
- mIconPackResources.put(compName, icon);
+ compName = new ComponentName(entry.toLowerCase(), "");
+ iconPackResources.put(compName, icon);
- int activityIndex = entry.lastIndexOf(".");
- if (activityIndex <= 0 || activityIndex == entry.length() - 1) {
- continue;
- }
+ int activityIndex = entry.lastIndexOf(".");
+ if (activityIndex <= 0 || activityIndex == entry.length() - 1) {
+ continue;
+ }
- String iconPackage = entry.substring(0, activityIndex);
- if (TextUtils.isEmpty(iconPackage)) {
- continue;
- }
+ String iconPackage = entry.substring(0, activityIndex);
+ if (TextUtils.isEmpty(iconPackage)) {
+ continue;
+ }
- String iconActivity = entry.substring(activityIndex + 1);
- if (TextUtils.isEmpty(iconActivity)) {
- continue;
- }
+ String iconActivity = entry.substring(activityIndex + 1);
+ if (TextUtils.isEmpty(iconActivity)) {
+ continue;
+ }
- // Store entries as lower case to ensure match
- iconPackage = iconPackage.toLowerCase();
- iconActivity = iconActivity.toLowerCase();
+ // Store entries as lower case to ensure match
+ iconPackage = iconPackage.toLowerCase();
+ iconActivity = iconActivity.toLowerCase();
- iconActivity = iconPackage + "." + iconActivity;
- compName = new ComponentName(iconPackage, iconActivity);
- mIconPackResources.put(compName, icon);
+ iconActivity = iconPackage + "." + iconActivity;
+ compName = new ComponentName(iconPackage, iconActivity);
+ iconPackResources.put(compName, icon);
+ }
+ } else {
+ loadApplicationResources(context, iconPackResources, packageName);
}
- mLoadedIconPackResource = res;
- mLoadedIconPackName = packageName;
+ return iconPackResources;
}
- public static void pickIconPack(final Context context) {
+ public static void pickIconPack(final Context context, final boolean pickIcon) {
final HashMap<CharSequence, String> supportedPackages = getSupportedPackages(context);
+ if (supportedPackages.isEmpty()) {
+ Toast.makeText(context, R.string.no_iconpacks_summary, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
final CharSequence[] dialogEntries = new CharSequence[supportedPackages.size() + 1];
supportedPackages.keySet().toArray(dialogEntries);
@@ -249,23 +309,42 @@ public class IconPackHelper {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.dialog_pick_iconpack_title);
- builder.setSingleChoiceItems(dialogEntries, selectedIndex, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- CharSequence selectedPackage = dialogEntries[which];
- if (selectedPackage.equals(defaultIcons)) {
- PreferencesProvider.Interface.General.setIconPack(context, "");
- } else {
- PreferencesProvider.Interface.General.setIconPack(context, supportedPackages.get(selectedPackage));
+ if (!pickIcon) {
+ builder.setSingleChoiceItems(dialogEntries, selectedIndex, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ CharSequence selectedPackage = dialogEntries[which];
+ if (selectedPackage.equals(defaultIcons)) {
+ PreferencesProvider.Interface.General.setIconPack(context, "");
+ } else {
+ PreferencesProvider.Interface.General.setIconPack(context, supportedPackages.get(selectedPackage));
+ }
+ dialog.dismiss();
}
- dialog.dismiss();
- }
- });
+ });
+ } else {
+ builder.setItems(dialogEntries, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ CharSequence selectedPackage = dialogEntries[which];
+ Launcher launcherActivity = (Launcher) context;
+ if (selectedPackage.equals(defaultIcons)) {
+ launcherActivity.onActivityResult(Launcher.REQUEST_PICK_ICON, Activity.RESULT_OK, null);
+ } else {
+ Intent i = new Intent();
+ i.setClass(context, IconPickerActivity.class);
+ i.putExtra("package", supportedPackages.get(selectedPackage));
+ launcherActivity.startActivityForResult(i, Launcher.REQUEST_PICK_ICON);
+ }
+ dialog.dismiss();
+ }
+ });
+ }
builder.show();
}
boolean isIconPackLoaded() {
return mLoadedIconPackResource != null &&
- mLoadedIconPackName != null;
+ mLoadedIconPackName != null &&
+ mIconPackResources != null;
}
private int getResourceIdForDrawable(String resource) {
diff --git a/src/com/cyanogenmod/trebuchet/IconPickerActivity.java b/src/com/cyanogenmod/trebuchet/IconPickerActivity.java
new file mode 100644
index 000000000..2acc07e4d
--- /dev/null
+++ b/src/com/cyanogenmod/trebuchet/IconPickerActivity.java
@@ -0,0 +1,151 @@
+package com.cyanogenmod.trebuchet;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+
+public class IconPickerActivity extends Activity {
+
+ public static final String SELECTED_RESOURCE_EXTRA = "selected_resource";
+ public static final String SELECTED_BITMAP_EXTRA = "bitmap";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ActivityManager activityManager =
+ (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ int iconSize = activityManager.getLauncherLargeIconSize();
+ final String pkgName = getIntent().getStringExtra("package");
+
+ GridView gridview = new GridView(this);
+ gridview.setNumColumns(GridView.AUTO_FIT);
+ gridview.setHorizontalSpacing(40);
+ gridview.setVerticalSpacing(40);
+ gridview.setPadding(20, 20, 20, 0);
+ gridview.setFastScrollEnabled(true);
+ gridview.setColumnWidth(iconSize);
+ gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
+
+ gridview.setAdapter(new ImageAdapter(this, pkgName));
+ gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View v, int position, long id) {
+ Intent in = new Intent();
+ DrawableInfo d = (DrawableInfo) adapterView.getAdapter().getItem(position);
+ in.putExtra(SELECTED_RESOURCE_EXTRA, pkgName + "|" + d.resource_name);
+ in.putExtra(SELECTED_BITMAP_EXTRA, ((BitmapDrawable)d.drawable.get()).getBitmap());
+ setResult(Activity.RESULT_OK, in);
+ finish();
+ }
+ });
+ setContentView(gridview);
+ }
+
+ public class ImageAdapter extends BaseAdapter {
+ private Context mContext;
+ private Resources mResources;
+ private ArrayList<DrawableInfo> mDrawables = new ArrayList<DrawableInfo>();
+
+ public class FetchDrawable extends AsyncTask<Integer, Void, Drawable> {
+ WeakReference<ImageView> mImageView;
+
+ FetchDrawable(ImageView imgView) {
+ mImageView = new WeakReference<ImageView>(imgView);
+ }
+
+ @Override
+ protected Drawable doInBackground(Integer... position) {
+ DrawableInfo info = getItem(position[0]);
+ int itemId = info.resource_id;
+ Drawable d = mResources.getDrawable(itemId);
+ info.drawable = new WeakReference<Drawable>(d);
+ return d;
+ }
+
+ @Override
+ public void onPostExecute(Drawable result) {
+ if (mImageView.get() != null) {
+ mImageView.get().setImageDrawable(result);
+ }
+ }
+ }
+
+ public ImageAdapter(Context c, String pkgName) {
+ mContext = c;
+ Map<ComponentName, String> resources = IconPackHelper.getIconPackResources(c, pkgName);
+ try {
+ mResources = c.getPackageManager().getResourcesForApplication(pkgName);
+ LinkedHashSet<String> drawables = new LinkedHashSet<String>(resources.values());
+ for (String s : drawables) {
+ int id = mResources.getIdentifier(s, "drawable", pkgName);
+ if (id != 0) {
+ mDrawables.add(new DrawableInfo(s, id));
+ }
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+
+ public int getCount() {
+ return mDrawables.size();
+ }
+
+ public DrawableInfo getItem(int position) {
+ return mDrawables.get(position);
+ }
+
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ final ImageView imageView;
+ if (convertView == null) {
+ imageView = new ImageView(mContext);
+ imageView.setLayoutParams(new GridView.LayoutParams(
+ GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT));
+ imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ } else {
+ imageView = (ImageView) convertView;
+ Object tag = imageView.getTag();
+ if (tag != null && tag instanceof FetchDrawable) {
+ ((FetchDrawable) tag).cancel(true);
+ }
+ }
+ FetchDrawable req = new FetchDrawable(imageView);
+ imageView.setTag(req);
+ req.execute(position);
+ return imageView;
+ }
+ }
+
+ private class DrawableInfo {
+ WeakReference<Drawable> drawable;
+ final String resource_name;
+ final int resource_id;
+ DrawableInfo(String n, int i) {
+ resource_name = n;
+ resource_id = i;
+ }
+ }
+}
diff --git a/src/com/cyanogenmod/trebuchet/Launcher.java b/src/com/cyanogenmod/trebuchet/Launcher.java
index 08e67cc57..dfd27048a 100644
--- a/src/com/cyanogenmod/trebuchet/Launcher.java
+++ b/src/com/cyanogenmod/trebuchet/Launcher.java
@@ -51,6 +51,7 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -99,6 +100,7 @@ import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.Advanceable;
import android.widget.EditText;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
@@ -117,6 +119,7 @@ import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -154,9 +157,9 @@ public final class Launcher extends Activity
private static final int REQUEST_PICK_SHORTCUT = 7;
private static final int REQUEST_PICK_APPWIDGET = 9;
private static final int REQUEST_PICK_WALLPAPER = 10;
- private static final int REQUEST_CREATE_LIVE_FOLDER = 12;
-
private static final int REQUEST_BIND_APPWIDGET = 11;
+ private static final int REQUEST_CREATE_LIVE_FOLDER = 12;
+ static final int REQUEST_PICK_ICON = 13;
static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
@@ -335,6 +338,7 @@ public final class Launcher extends Activity
private boolean mFullscreenMode;
private boolean mWallpaperVisible;
+ private ImageButton mDialogIcon;
private Runnable mBuildLayersRunnable = new Runnable() {
public void run() {
@@ -679,6 +683,60 @@ public final class Launcher extends Activity
addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, mPendingAddWidgetInfo);
}
return;
+ } else if (requestCode == REQUEST_PICK_ICON) {
+ mWaitingForResult = false;
+ if (resultCode == RESULT_OK) {
+ if (data == null) {
+ // Get/Set default icon
+ String id = (String) mDialogIcon.getTag();
+ final PackageManager manager = getPackageManager();
+
+ final Cursor c = getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ null, LauncherSettings.Favorites._ID + "=?", new String[]{id}, null);
+ if (c != null && c.getCount() > 0) {
+ c.moveToFirst();
+ final int itemTypeIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ITEM_TYPE);
+ final int titleIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.TITLE);
+ final int iconTypeIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ICON_TYPE);
+ final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ final int iconPackageIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ICON_PACKAGE);
+ final int iconResourceIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ICON_RESOURCE);
+ final int intentIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.INTENT);
+ String intentDescription = c.getString(intentIndex);
+ Intent intent = null;
+ try {
+ intent = Intent.parseUri(intentDescription, 0);
+ } catch (URISyntaxException e) {
+ c.close();
+ return;
+ }
+ int itemType = c.getInt(itemTypeIndex);
+ ShortcutInfo info = null;
+ if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ info = mModel.getShortcutInfo(manager, intent, this, c, iconIndex,
+ titleIndex, -1, null);
+ } else if (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+ info = mModel.getShortcutInfo(c, this, iconTypeIndex,
+ iconPackageIndex, iconResourceIndex, iconIndex,
+ titleIndex, -1);
+ }
+ mDialogIcon.setImageBitmap(info.getIcon(null));
+ mDialogIcon.setTag(null);
+ c.close();
+ }
+ } else {
+ // Set custom icon from icon pack
+ mDialogIcon.setImageBitmap((Bitmap) data.getParcelableExtra(IconPickerActivity.SELECTED_BITMAP_EXTRA));
+ mDialogIcon.setTag(data.getStringExtra(IconPickerActivity.SELECTED_RESOURCE_EXTRA));
+ }
+ }
+ return;
}
boolean delayExitSpringLoadedMode = false;
boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET ||
@@ -1089,8 +1147,16 @@ public final class Launcher extends Activity
void updateShortcut(final ShortcutInfo info) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
View layout = mInflater.inflate(R.layout.dialog_edit, null);
- ImageView icon = (ImageView) layout.findViewById(R.id.dialog_edit_icon);
- icon.setImageBitmap(info.getIcon(mIconCache));
+ mDialogIcon = (ImageButton) layout.findViewById(R.id.dialog_edit_icon);
+ mDialogIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ mDialogIcon.setImageBitmap(info.getIcon(mIconCache));
+ mDialogIcon.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mDialogIcon.setTag(String.valueOf(info.id));
+ IconPackHelper.pickIconPack(Launcher.this, true);
+ }
+ });
final EditText title = (EditText) layout.findViewById(R.id.dialog_edit_text);
title.setText(info.title);
builder.setView(layout)
@@ -1098,12 +1164,31 @@ public final class Launcher extends Activity
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- info.setTitle(title.getText());
+ if (!info.title.equals(title.getText())) {
+ info.setTitle(title.getText());
+ }
+ if (mDialogIcon.getTag() != null) {
+ info.customIconResource = (String) mDialogIcon.getTag();
+ Drawable d = mModel.getDrawableForCustomIcon(Launcher.this, info.customIconResource);
+ if (d != null) {
+ info.setIcon(Utilities.createIconBitmap(d, Launcher.this));
+ }
+ } else {
+ info.customIconResource = null;
+ info.setIcon(((BitmapDrawable)mDialogIcon.getDrawable()).getBitmap());
+ }
+
LauncherModel.updateItemInDatabase(Launcher.this, info);
}
})
.setNegativeButton(android.R.string.cancel, null);
builder.show();
+ builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mDialogIcon = null;
+ }
+ });
}
/**
diff --git a/src/com/cyanogenmod/trebuchet/LauncherModel.java b/src/com/cyanogenmod/trebuchet/LauncherModel.java
index ba8eb6a63..08efc6fa8 100644
--- a/src/com/cyanogenmod/trebuchet/LauncherModel.java
+++ b/src/com/cyanogenmod/trebuchet/LauncherModel.java
@@ -36,6 +36,7 @@ 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.os.Environment;
import android.os.Handler;
@@ -44,6 +45,7 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Log;
import com.cyanogenmod.trebuchet.preference.PreferencesProvider;
@@ -1358,6 +1360,8 @@ public class LauncherModel extends BroadcastReceiver {
LauncherSettings.Favorites.SPANY);
final int receiverPackageIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.RECEIVER_COMPONENT);
+ final int customIconIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.CUSTOM_ICON);
ShortcutInfo info;
String intentDescription;
@@ -1384,11 +1388,11 @@ public class LauncherModel extends BroadcastReceiver {
if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
info = getShortcutInfo(manager, intent, context, c, iconIndex,
- titleIndex, mLabelCache);
+ titleIndex, customIconIndex, mLabelCache);
} else if (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex,
- titleIndex);
+ titleIndex, customIconIndex);
// App shortcuts that used to be automatically added to Launcher
// didn't always have the correct intent flags set, so do that
@@ -1404,7 +1408,7 @@ public class LauncherModel extends BroadcastReceiver {
} else {
info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex,
- titleIndex);
+ titleIndex, -1);
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_ALLAPPS;
if (info.title == null) {
info.title = mContext.getString(R.string.all_apps_button_label);
@@ -2245,7 +2249,7 @@ public class LauncherModel extends BroadcastReceiver {
* doesn't have a Cursor, but
*/
public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {
- return getShortcutInfo(manager, intent, context, null, -1, -1, null);
+ return getShortcutInfo(manager, intent, context, null, -1, -1, -1, null);
}
/**
@@ -2254,7 +2258,7 @@ public class LauncherModel extends BroadcastReceiver {
* If c is not null, then it will be used to fill in missing data like the title and icon.
*/
public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,
- Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {
+ Cursor c, int iconIndex, int titleIndex, int customIconIndex, HashMap<Object, CharSequence> labelCache) {
Bitmap icon = null;
final ShortcutInfo info = new ShortcutInfo();
@@ -2315,6 +2319,11 @@ public class LauncherModel extends BroadcastReceiver {
icon = getFallbackIcon();
info.usingFallbackIcon = true;
}
+ Bitmap customIcon = getCustomIconFromCursor(c, context, customIconIndex);
+ if (customIcon != null) {
+ icon = customIcon;
+ }
+
info.setIcon(icon);
// from the db
@@ -2361,12 +2370,42 @@ public class LauncherModel extends BroadcastReceiver {
return items;
}
+ public Drawable getDrawableForCustomIcon(Context context, String customIconResource) {
+ String[] splitResource = customIconResource.split("\\|");
+ String packageName = splitResource[0];
+ String resource = splitResource[1];
+ PackageManager packageManager = context.getPackageManager();
+ Resources resources;
+ try {
+ resources = packageManager.getResourcesForApplication(packageName);
+ int id = resources.getIdentifier(resource, "drawable", packageName);
+ return mIconCache.getFullResIcon(resources, id);
+ } catch (NameNotFoundException e) {
+ }
+ return null;
+ }
+
+ private Bitmap getCustomIconFromCursor(Cursor c, Context context, int customIconIndex) {
+ if (c == null || customIconIndex == -1) {
+ return null;
+ }
+ String customIconResource = c.getString(customIconIndex);
+ if (!TextUtils.isEmpty(customIconResource)) {
+ Drawable d = getDrawableForCustomIcon(context, customIconResource);
+ if (d != null) {
+ return Utilities.createIconBitmap(
+ d, context);
+ }
+ }
+ return null;
+ }
+
/**
* Make an ShortcutInfo object for a shortcut that isn't an application.
*/
- private ShortcutInfo getShortcutInfo(Cursor c, Context context,
+ public ShortcutInfo getShortcutInfo(Cursor c, Context context,
int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,
- int titleIndex) {
+ int titleIndex, int customIconIndex) {
Bitmap icon = null;
final ShortcutInfo info = new ShortcutInfo();
@@ -2420,6 +2459,10 @@ public class LauncherModel extends BroadcastReceiver {
info.customIcon = false;
break;
}
+ Bitmap customIcon = getCustomIconFromCursor(c, context, customIconIndex);
+ if (customIcon != null) {
+ icon = customIcon;
+ }
info.setIcon(icon);
return info;
}
diff --git a/src/com/cyanogenmod/trebuchet/LauncherProvider.java b/src/com/cyanogenmod/trebuchet/LauncherProvider.java
index 4805962aa..00220b183 100644
--- a/src/com/cyanogenmod/trebuchet/LauncherProvider.java
+++ b/src/com/cyanogenmod/trebuchet/LauncherProvider.java
@@ -62,7 +62,7 @@ public class LauncherProvider extends ContentProvider {
private static final String DATABASE_NAME = "launcher.db";
- private static final int DATABASE_VERSION = 15;
+ private static final int DATABASE_VERSION = 16;
static final String AUTHORITY = "com.cyanogenmod.trebuchet.settings";
@@ -290,7 +290,8 @@ public class LauncherProvider extends ContentProvider {
"iconPackage TEXT," +
"iconResource TEXT," +
"icon BLOB," +
- "receiverComponent TEXT" +
+ "receiverComponent TEXT," +
+ "customIcon TEXT" +
");");
// Database was just created, so wipe any previous widgets
@@ -439,6 +440,10 @@ public class LauncherProvider extends ContentProvider {
version = 15;
}
+ if (oldVersion < 16) {
+ db.execSQL("ALTER TABLE favorites ADD customIcon TEXT;");
+ version = 16;
+ }
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
diff --git a/src/com/cyanogenmod/trebuchet/LauncherSettings.java b/src/com/cyanogenmod/trebuchet/LauncherSettings.java
index f855139b1..aa52d0480 100644
--- a/src/com/cyanogenmod/trebuchet/LauncherSettings.java
+++ b/src/com/cyanogenmod/trebuchet/LauncherSettings.java
@@ -99,6 +99,8 @@ class LauncherSettings {
* <P>Type: BLOB</P>
*/
static final String ICON = "icon";
+
+ static final String CUSTOM_ICON = "customIcon";
}
/**
diff --git a/src/com/cyanogenmod/trebuchet/ShortcutInfo.java b/src/com/cyanogenmod/trebuchet/ShortcutInfo.java
index 2924de675..14fd0c0fa 100644
--- a/src/com/cyanogenmod/trebuchet/ShortcutInfo.java
+++ b/src/com/cyanogenmod/trebuchet/ShortcutInfo.java
@@ -35,6 +35,7 @@ class ShortcutInfo extends ItemInfo {
*/
Intent intent;
+ String customIconResource;
/**
* Indicates whether the title comes from an application's resource (if false)
* or from a custom title (if true.)
@@ -67,7 +68,8 @@ class ShortcutInfo extends ItemInfo {
/**
* Title change listener
*/
- private ShortcutListener mListener;
+ private ArrayList<ShortcutListener> mListeners =
+ new ArrayList<ShortcutListener>();
/**
* The shortcut folder information
@@ -104,6 +106,9 @@ class ShortcutInfo extends ItemInfo {
public void setIcon(Bitmap b) {
mIcon = b;
+ for (ShortcutListener i : mListeners) {
+ i.onIconChanged(this);
+ }
}
public Bitmap getIcon(IconCache iconCache) {
@@ -136,13 +141,15 @@ class ShortcutInfo extends ItemInfo {
public void setTitle(CharSequence title) {
this.title = title;
this.customTitle = true;
- if (mListener != null) {
- mListener.onTitleChanged(title);
+ for (ShortcutListener i : mListeners) {
+ i.onTitleChanged(this);
}
}
void setListener(ShortcutListener listener) {
- mListener = listener;
+ if (!mListeners.contains(listener) && listener != null) {
+ mListeners.add(listener);
+ }
}
@Override
@@ -156,6 +163,7 @@ class ShortcutInfo extends ItemInfo {
String uri = intent != null ? intent.toUri(0) : null;
values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
+ values.put(LauncherSettings.BaseLauncherColumns.CUSTOM_ICON, customIconResource);
if (customIcon) {
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
@@ -193,7 +201,8 @@ class ShortcutInfo extends ItemInfo {
}
interface ShortcutListener {
- public void onTitleChanged(CharSequence title);
+ public void onTitleChanged(ShortcutInfo item);
+ public void onIconChanged(ShortcutInfo item);
}
}
diff --git a/src/com/cyanogenmod/trebuchet/preference/Preferences.java b/src/com/cyanogenmod/trebuchet/preference/Preferences.java
index f2fcec8be..2f66a65c6 100644
--- a/src/com/cyanogenmod/trebuchet/preference/Preferences.java
+++ b/src/com/cyanogenmod/trebuchet/preference/Preferences.java
@@ -193,7 +193,7 @@ public class Preferences extends PreferenceActivity
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
if (preference.getKey().equals("ui_general_iconpack")) {
- IconPackHelper.pickIconPack(getActivity());
+ IconPackHelper.pickIconPack(getActivity(), false);
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}