/*
* Copyright (C) 2012 The CyanogenMod 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.settings.cyanogenmod;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.widget.multiwaveview.GlowPadView;
import com.android.internal.widget.multiwaveview.TargetDrawable;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.cyanogenmod.IconPicker.OnIconPickListener;
public class LockscreenTargets extends Fragment implements ShortcutPickHelper.OnPickListener,
GlowPadView.OnTriggerListener, OnIconPickListener {
private GlowPadView mWaveView;
private ImageButton mDialogIcon;
private Button mDialogLabel;
private ShortcutPickHelper mPicker;
private IconPicker mIconPicker;
private ArrayList<TargetInfo> mTargetStore = new ArrayList<TargetInfo>();
private int mTargetOffset;
private int mTargetInset;
private boolean mIsLandscape;
private boolean mIsScreenLarge;
private ViewGroup mContainer;
private Activity mActivity;
private Resources mResources;
private File mImageTmp;
private int mTargetIndex = 0;
private static final int MENU_RESET = Menu.FIRST;
private static final int MENU_SAVE = Menu.FIRST + 1;
private static String EMPTY_LABEL;
class TargetInfo {
String uri, pkgName;
StateListDrawable icon;
Drawable defaultIcon;
String iconType;
String iconSource;
TargetInfo(StateListDrawable target) {
icon = target;
}
TargetInfo(String in, StateListDrawable target, String iType, String iSource, Drawable dI) {
uri = in;
icon = target;
defaultIcon = dI;
iconType = iType;
iconSource = iSource;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mContainer = container;
setHasOptionsMenu(true);
mActivity = getActivity();
mIsScreenLarge = !Utils.isPhone(mActivity);
mResources = getResources();
mIsLandscape = mResources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
mTargetOffset = mIsLandscape && !mIsScreenLarge ? 2 : 0;
mTargetInset = mResources.getDimensionPixelSize(com.android.internal.R.dimen.lockscreen_target_inset);
mIconPicker = new IconPicker(mActivity, this);
mPicker = new ShortcutPickHelper(mActivity, this);
mImageTmp = new File(mActivity.getCacheDir() + "/target.tmp");
EMPTY_LABEL = mActivity.getResources().getString(R.string.lockscreen_target_empty);
return inflater.inflate(R.layout.lockscreen_targets, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mWaveView = ((GlowPadView) mActivity.findViewById(R.id.lock_target));
mWaveView.setOnTriggerListener(this);
initializeView(Settings.System.getString(mActivity.getContentResolver(), Settings.System.LOCKSCREEN_TARGETS));
}
/**
* Create a layered drawable
* @param back - Background image to use when target is active
* @param front - Front image to use for target
* @param inset - Target inset padding
* @param frontBlank - Whether the front image for active target should be blank
* @return StateListDrawable
*/
private StateListDrawable getLayeredDrawable(Drawable back, Drawable front, int inset, boolean frontBlank) {
front.mutate();
back.mutate();
InsetDrawable[] inactivelayer = new InsetDrawable[2];
InsetDrawable[] activelayer = new InsetDrawable[2];
Drawable activeFront = frontBlank ? mResources.getDrawable(android.R.color.transparent) : front;
Drawable inactiveBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_lock_pressed);
inactivelayer[0] = new InsetDrawable(inactiveBack, 0, 0, 0, 0);
inactivelayer[1] = new InsetDrawable(front, inset, inset, inset, inset);
activelayer[0] = new InsetDrawable(back, 0, 0, 0, 0);
activelayer[1] = new InsetDrawable(activeFront, inset, inset, inset, inset);
StateListDrawable states = new StateListDrawable();
LayerDrawable inactiveLayerDrawable = new LayerDrawable(inactivelayer);
inactiveLayerDrawable.setId(0, 0);
inactiveLayerDrawable.setId(1, 1);
LayerDrawable activeLayerDrawable = new LayerDrawable(activelayer);
activeLayerDrawable.setId(0, 0);
activeLayerDrawable.setId(1, 1);
states.addState(TargetDrawable.STATE_INACTIVE, inactiveLayerDrawable);
states.addState(TargetDrawable.STATE_ACTIVE, activeLayerDrawable);
states.addState(TargetDrawable.STATE_FOCUSED, activeLayerDrawable);
return states;
}
private void initializeView(String input) {
if (input == null) {
input = GlowPadView.EMPTY_TARGET;
}
mTargetStore.clear();
final int maxTargets = mIsScreenLarge ? GlowPadView.MAX_TABLET_TARGETS : GlowPadView.MAX_PHONE_TARGETS;
final PackageManager packMan = mActivity.getPackageManager();
final Drawable activeBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_target_activated);
final String[] targetStore = input.split("\\|");
//Shift by 2 targets for phones in landscape
if (mIsLandscape && !mIsScreenLarge) {
mTargetStore.add(new TargetInfo(null));
mTargetStore.add(new TargetInfo(null));
}
//Add the unlock icon
Drawable unlockFront = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_unlock_normal);
Drawable unlockBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_unlock_activated);
mTargetStore.add(new TargetInfo(getLayeredDrawable(unlockBack, unlockFront, 0, true)));
for (int cc = 0; cc < 8 - mTargetOffset - 1; cc++) {
String uri = GlowPadView.EMPTY_TARGET;
Drawable front = null;
Drawable back = activeBack;
boolean frontBlank = false;
String iconType = null;
String iconSource = null;
int tmpInset = mTargetInset;
if (cc < targetStore.length && cc < maxTargets) {
uri = targetStore[cc];
if (!uri.equals(GlowPadView.EMPTY_TARGET)) {
try {
Intent in = Intent.parseUri(uri, 0);
if (in.hasExtra(GlowPadView.ICON_FILE)) {
String rSource = in.getStringExtra(GlowPadView.ICON_FILE);
File fPath = new File(rSource);
if (fPath != null) {
if (fPath.exists()) {
front = new BitmapDrawable(getResources(), getRoundedCornerBitmap(BitmapFactory.decodeFile(rSource)));
tmpInset = tmpInset + 5;
}
}
} else if (in.hasExtra(GlowPadView.ICON_RESOURCE)) {
String rSource = in.getStringExtra(GlowPadView.ICON_RESOURCE);
String rPackage = in.getStringExtra(GlowPadView.ICON_PACKAGE);
if (rSource != null) {
if (rPackage != null) {
try {
Context rContext = mActivity.createPackageContext(rPackage, 0);
int id = rContext.getResources().getIdentifier(rSource, "drawable", rPackage);
front = rContext.getResources().getDrawable(id);
id = rContext.getResources().getIdentifier(rSource.replaceAll("_normal", "_activated"),
"drawable", rPackage);
back = rContext.getResources().getDrawable(id);
tmpInset = 0;
frontBlank = true;
} catch (NameNotFoundException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
} else {
front = mResources.getDrawable(mResources.getIdentifier(rSource, "drawable", "android"));
back = mResources.getDrawable(mResources.getIdentifier(
rSource.replaceAll("_normal", "_activated"), "drawable", "android"));
tmpInset = 0;
frontBlank = true;
}
}
}
if (front == null) {
ActivityInfo aInfo = in.resolveActivityInfo(packMan, PackageManager.GET_ACTIVITIES);
if (aInfo != null) {
front = aInfo.loadIcon(packMan);
} else {
front = mResources.getDrawable(android.R.drawable.sym_def_app_icon).mutate();
}
}
} catch (Exception e) {
}
}
} else if (cc >= maxTargets) {
mTargetStore.add(new TargetInfo(null));
continue;
}
if (back == null || front == null) {
Drawable emptyIcon = mResources.getDrawable(R.drawable.ic_empty).mutate();
front = emptyIcon;
}
mTargetStore.add(new TargetInfo(uri, getLayeredDrawable(back,front, tmpInset, frontBlank), iconType,
iconSource, front.getConstantState().newDrawable().mutate()));
}
ArrayList<TargetDrawable> tDraw = new ArrayList<TargetDrawable>();
for (TargetInfo i : mTargetStore) {
if (i != null) {
tDraw.add(new TargetDrawable(mResources, i.icon));
} else {
tDraw.add(new TargetDrawable(mResources, null));
}
}
mWaveView.setTargetResources(tDraw);
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = 24;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
@Override
public void onResume() {
super.onResume();
// If running on a phone, remove padding around container
if (!mIsScreenLarge) {
mContainer.setPadding(0, 0, 0, 0);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_RESET, 0, R.string.profile_reset_title)
.setIcon(R.drawable.ic_settings_backup) // use the backup icon
.setAlphabeticShortcut('r')
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add(0, MENU_SAVE, 0, R.string.wifi_save)
.setIcon(R.drawable.ic_menu_save)
.setAlphabeticShortcut('s')
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_RESET:
resetAll();
return true;
case MENU_SAVE:
saveAll();
Toast.makeText(mActivity, R.string.lockscreen_target_save, Toast.LENGTH_LONG).show();
return true;
default:
return false;
}
}
/**
* Resets the target layout to stock
*/
private void resetAll() {
new AlertDialog.Builder(mActivity)
.setTitle(R.string.lockscreen_target_reset_title)
.setIconAttribute(android.R.attr.alertDialogIcon)
.setMessage(R.string.lockscreen_target_reset_message)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
initializeView(null);
Settings.System.putString(mActivity.getContentResolver(), Settings.System.LOCKSCREEN_TARGETS, null);
Toast.makeText(mActivity, R.string.lockscreen_target_reset, Toast.LENGTH_LONG).show();
}
}).setNegativeButton(R.string.cancel, null)
.create().show();
}
/**
* Save targets to settings provider
*/
private void saveAll() {
StringBuilder targetLayout = new StringBuilder();
ArrayList<String> existingImages = new ArrayList<String>();
final int maxTargets = mIsScreenLarge ? GlowPadView.MAX_TABLET_TARGETS : GlowPadView.MAX_PHONE_TARGETS;
for (int i = mTargetOffset + 1; i <= mTargetOffset + maxTargets; i++) {
String uri = mTargetStore.get(i).uri;
String type = mTargetStore.get(i).iconType;
String source = mTargetStore.get(i).iconSource;
existingImages.add(source);
if (!uri.equals(GlowPadView.EMPTY_TARGET) && type != null) {
try {
Intent in = Intent.parseUri(uri, 0);
in.putExtra(type, source);
String pkgName = mTargetStore.get(i).pkgName;
if (pkgName != null) {
in.putExtra(GlowPadView.ICON_PACKAGE, mTargetStore.get(i).pkgName);
} else {
in.removeExtra(GlowPadView.ICON_PACKAGE);
}
uri = in.toUri(0);
} catch (URISyntaxException e) {
}
}
targetLayout.append(uri);
targetLayout.append("|");
}
targetLayout.deleteCharAt(targetLayout.length() - 1);
Settings.System.putString(mActivity.getContentResolver(), Settings.System.LOCKSCREEN_TARGETS, targetLayout.toString());
for (File pic : mActivity.getFilesDir().listFiles()) {
if (pic.getName().startsWith("lockscreen_") && !existingImages.contains(pic.toString())) {
pic.delete();
}
}
}
/**
* Updates a target in the GlowPadView
*/
private void setTarget(int position, String uri, Drawable draw, String iconType, String iconSource, String pkgName) {
TargetInfo item = mTargetStore.get(position);
StateListDrawable state = (StateListDrawable) item.icon;
LayerDrawable inActiveLayer = (LayerDrawable) state.getStateDrawable(0);
LayerDrawable activeLayer = (LayerDrawable) state.getStateDrawable(1);
inActiveLayer.setDrawableByLayerId(1, draw);
boolean isSystem = iconType != null && iconType.equals(GlowPadView.ICON_RESOURCE);
if (!isSystem) {
final Drawable activeBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_target_activated);
activeLayer.setDrawableByLayerId(0, new InsetDrawable(activeBack, 0, 0, 0, 0));
activeLayer.setDrawableByLayerId(1, draw);
} else {
InsetDrawable empty = new InsetDrawable(mResources.getDrawable(android.R.color.transparent), 0, 0, 0, 0);
activeLayer.setDrawableByLayerId(1, empty);
int activeId = mResources.getIdentifier(iconSource.replaceAll("_normal", "_activated"), "drawable", "android");
Drawable back = null;
if (activeId != 0) {
back = mResources.getDrawable(activeId);
activeLayer.setDrawableByLayerId(0, back);
} else {
final Drawable activeBack = mResources.getDrawable(com.android.internal.R.drawable.ic_lockscreen_target_activated);
activeLayer.setDrawableByLayerId(0, new InsetDrawable(activeBack, 0, 0, 0, 0));
}
}
item.defaultIcon = mDialogIcon.getDrawable().getConstantState().newDrawable().mutate();
item.uri = uri;
item.iconType = iconType;
item.iconSource = iconSource;
item.pkgName = pkgName;
}
@Override
public void shortcutPicked(String uri, String friendlyName, boolean isApplication) {
try {
Intent i = Intent.parseUri(uri, 0);
PackageManager pm = mActivity.getPackageManager();
ActivityInfo aInfo = i.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES);
Drawable icon = null;
if (aInfo != null) {
icon = aInfo.loadIcon(pm).mutate();
} else {
icon = mResources.getDrawable(android.R.drawable.sym_def_app_icon);
}
mDialogLabel.setText(friendlyName);
mDialogLabel.setTag(uri);
mDialogIcon.setImageDrawable(resizeForDialog(icon));
mDialogIcon.setTag(null);
} catch (Exception e) {
}
}
private Drawable resizeForDialog(Drawable image) {
int size = (int) mResources.getDimension(android.R.dimen.app_icon_size);
Bitmap d = ((BitmapDrawable)image).getBitmap();
Bitmap bitmapOrig = Bitmap.createScaledBitmap(d, size, size, false);
return new BitmapDrawable(mResources, bitmapOrig);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
String shortcut_name = null;
if (data != null) {
shortcut_name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
}
if (shortcut_name != null && shortcut_name.equals(EMPTY_LABEL)) {
mDialogLabel.setText(EMPTY_LABEL);
mDialogLabel.setTag(GlowPadView.EMPTY_TARGET);
mDialogIcon.setImageResource(R.drawable.ic_empty);
} else if (requestCode == IconPicker.REQUEST_PICK_SYSTEM || requestCode == IconPicker.REQUEST_PICK_GALLERY
|| requestCode == IconPicker.REQUEST_PICK_ICON_PACK) {
mIconPicker.onActivityResult(requestCode, resultCode, data);
} else if (requestCode != Activity.RESULT_CANCELED && resultCode != Activity.RESULT_CANCELED) {
mPicker.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onGrabbed(View v, int handle) {
}
@Override
public void onReleased(View v, int handle) {
}
@Override
public void onTrigger(View v, final int target) {
mTargetIndex = target;
if ((target != 0 && (mIsScreenLarge || !mIsLandscape)) || (target != 2 && !mIsScreenLarge && mIsLandscape)) {
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(R.string.lockscreen_target_edit_title);
builder.setMessage(R.string.lockscreen_target_edit_msg);
View view = View.inflate(mActivity, R.layout.lockscreen_shortcut_dialog, null);
view.findViewById(R.id.icon).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mDialogLabel.getText().equals(EMPTY_LABEL)) {
try {
mImageTmp.createNewFile();
mImageTmp.setWritable(true, false);
mIconPicker.pickIcon(getId(), mImageTmp);
} catch (IOException e) {
}
}
}
});
view.findViewById(R.id.label).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPicker.pickShortcut(new String[] {EMPTY_LABEL}, new ShortcutIconResource[] {
ShortcutIconResource.fromContext(mActivity, android.R.drawable.ic_delete) }, getId());
}
});
mDialogIcon = ((ImageButton) view.findViewById(R.id.icon));
mDialogLabel = ((Button) view.findViewById(R.id.label));
TargetInfo item = mTargetStore.get(target);
mDialogIcon.setImageDrawable(mTargetStore.get(target).defaultIcon.mutate());
TargetInfo tmpIcon = new TargetInfo(null);
tmpIcon.iconType = item.iconType;
tmpIcon.iconSource = item.iconSource;
tmpIcon.pkgName = item.pkgName;
mDialogIcon.setTag(tmpIcon);
if (mTargetStore.get(target).uri.equals(GlowPadView.EMPTY_TARGET)) {
mDialogLabel.setText(EMPTY_LABEL);
} else {
mDialogLabel.setText(mPicker.getFriendlyNameForUri(mTargetStore.get(target).uri));
}
mDialogLabel.setTag(mTargetStore.get(target).uri);
builder.setView(view);
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
TargetInfo vObject = (TargetInfo) mDialogIcon.getTag();
String type = null, source = null, pkgName = null;
int targetInset = mTargetInset;
if (vObject != null) {
type = vObject.iconType;
source = vObject.iconSource;
pkgName = vObject.pkgName;
}
if (type != null && type.equals(GlowPadView.ICON_RESOURCE)) {
targetInset = 0;
}
InsetDrawable pD = new InsetDrawable(mDialogIcon.getDrawable(), targetInset,
targetInset, targetInset, targetInset);
setTarget(mTargetIndex, mDialogLabel.getTag().toString(), pD, type, source, pkgName);
}
});
builder.setNegativeButton(R.string.cancel, null);
builder.setCancelable(false);
AlertDialog dialog = builder.create();
dialog.show();
((TextView)dialog.findViewById(android.R.id.message)).setTextAppearance(mActivity,
android.R.style.TextAppearance_DeviceDefault_Small);
}
}
@Override
public void onGrabbedStateChange(View v, int handle) {
}
@Override
public void iconPicked(int requestCode, int resultCode, Intent in) {
Drawable ic = null;
String iconType = null;
String pkgName = null;
String iconSource = null;
if (requestCode == IconPicker.REQUEST_PICK_GALLERY) {
if (resultCode == Activity.RESULT_OK) {
File mImage = new File(mActivity.getFilesDir() + "/lockscreen_" + System.currentTimeMillis() + ".png");
if (mImageTmp.exists()) {
mImageTmp.renameTo(mImage);
}
mImage.setReadOnly();
iconType = GlowPadView.ICON_FILE;
iconSource = mImage.toString();
ic = new BitmapDrawable(getResources(), BitmapFactory.decodeFile(mImage.toString()));
} else {
if (mImageTmp.exists()) {
mImageTmp.delete();
}
return;
}
} else if (requestCode == IconPicker.REQUEST_PICK_SYSTEM) {
String resourceName = in.getStringExtra(IconPicker.RESOURCE_NAME);
ic = mResources.getDrawable(mResources.getIdentifier(resourceName, "drawable", "android")).mutate();
iconType = GlowPadView.ICON_RESOURCE;
iconSource = resourceName;
} else if (requestCode == IconPicker.REQUEST_PICK_ICON_PACK && resultCode == Activity.RESULT_OK) {
String resourceName = in.getStringExtra(IconPicker.RESOURCE_NAME);
pkgName = in.getStringExtra(IconPicker.PACKAGE_NAME);
try {
Context rContext = mActivity.createPackageContext(pkgName, 0);
int id = rContext.getResources().getIdentifier(resourceName, "drawable", pkgName);
ic = rContext.getResources().getDrawable(id);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
iconType = GlowPadView.ICON_RESOURCE;
iconSource = resourceName;
} else {
return;
}
TargetInfo tmpIcon = new TargetInfo(null);
tmpIcon.iconType = iconType;
tmpIcon.iconSource = iconSource;
tmpIcon.pkgName = pkgName;
mDialogIcon.setTag(tmpIcon);
mDialogIcon.setImageDrawable(ic);
}
@Override
public void onFinishFinalAnimation() {
}
}