Reformat code to match intellij style

This commit is contained in:
SVolf 2023-09-23 10:38:21 +07:00 committed by TrianguloY
parent 836d879a4f
commit dcf8e580a9
248 changed files with 49825 additions and 48471 deletions

View file

@ -19,7 +19,7 @@ package com.google.android.vending.licensing;
import com.google.android.vending.licensing.util.Base64;
import com.google.android.vending.licensing.util.Base64DecoderException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.spec.KeySpec;
@ -40,23 +40,23 @@ public class AESObfuscator implements Obfuscator {
private static final String KEYGEN_ALGORITHM = "PBEWITHSHAAND256BITAES-CBC-BC";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final byte[] IV =
{ 16, 74, 71, -80, 32, 101, -47, 72, 117, -14, 0, -29, 70, 65, -12, 74 };
{16, 74, 71, -80, 32, 101, -47, 72, 117, -14, 0, -29, 70, 65, -12, 74};
private static final String header = "com.android.vending.licensing.AESObfuscator-1|";
private Cipher mEncryptor;
private Cipher mDecryptor;
private final Cipher mEncryptor;
private final Cipher mDecryptor;
/**
* @param salt an array of random bytes to use for each (un)obfuscation
* @param salt an array of random bytes to use for each (un)obfuscation
* @param applicationId application identifier, e.g. the package name
* @param deviceId device identifier. Use as many sources as possible to
* create this unique identifier.
* @param deviceId device identifier. Use as many sources as possible to
* create this unique identifier.
*/
public AESObfuscator(byte[] salt, String applicationId, String deviceId) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEYGEN_ALGORITHM);
KeySpec keySpec =
new PBEKeySpec((applicationId + deviceId).toCharArray(), salt, 1024, 256);
KeySpec keySpec =
new PBEKeySpec((applicationId + deviceId).toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
mEncryptor = Cipher.getInstance(CIPHER_ALGORITHM);
@ -75,9 +75,7 @@ public class AESObfuscator implements Obfuscator {
}
try {
// Header is appended as an integrity check
return Base64.encode(mEncryptor.doFinal((header + key + original).getBytes(UTF8)));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Invalid environment", e);
return Base64.encode(mEncryptor.doFinal((header + key + original).getBytes(StandardCharsets.UTF_8)));
} catch (GeneralSecurityException e) {
throw new RuntimeException("Invalid environment", e);
}
@ -88,23 +86,21 @@ public class AESObfuscator implements Obfuscator {
return null;
}
try {
String result = new String(mDecryptor.doFinal(Base64.decode(obfuscated)), UTF8);
String result = new String(mDecryptor.doFinal(Base64.decode(obfuscated)), StandardCharsets.UTF_8);
// Check for presence of header. This serves as a final integrity check, for cases
// where the block size is correct during decryption.
int headerIndex = result.indexOf(header+key);
int headerIndex = result.indexOf(header + key);
if (headerIndex != 0) {
throw new ValidationException("Header not found (invalid data or key)" + ":" +
obfuscated);
}
return result.substring(header.length()+key.length(), result.length());
return result.substring(header.length() + key.length());
} catch (Base64DecoderException e) {
throw new ValidationException(e.getMessage() + ":" + obfuscated);
} catch (IllegalBlockSizeException e) {
throw new ValidationException(e.getMessage() + ":" + obfuscated);
} catch (BadPaddingException e) {
throw new ValidationException(e.getMessage() + ":" + obfuscated);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Invalid environment", e);
}
}
}

View file

@ -17,9 +17,7 @@
package com.google.android.vending.licensing;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.util.Log;
import net.pierrox.lightning_launcher.data.FileUtils;
@ -32,15 +30,15 @@ import java.io.IOException;
public class JSONDataObfuscator {
private static final byte[] SALT = new byte[] {
private static final byte[] SALT = new byte[]{
42, 13, 27, -7, 1, 63, -51, 94, 107, 120, 4,
-54, -77, 123, -12, -72, -99, 10, 0, 73
};
private File mFile;
private String mPackageName;
private JSONObject mData;
private final File mFile;
private final String mPackageName;
private final Obfuscator mObfuscator;
private JSONObject mData;
public JSONDataObfuscator(Context context) {
@ -49,10 +47,10 @@ public class JSONDataObfuscator {
mFile = new File(context.getCacheDir(), "icon");
mObfuscator = new AESObfuscator(SALT, mPackageName, deviceId);
String obfuscated_data = FileUtils.readFileContent(mFile);
if(obfuscated_data != null) {
if (obfuscated_data != null) {
try {
String data = mObfuscator.unobfuscate(obfuscated_data, context.getPackageName());
if(data != null) {
if (data != null) {
mData = new JSONObject(data);
}
} catch (Exception e) {
@ -60,7 +58,7 @@ public class JSONDataObfuscator {
}
}
if(mData == null) {
if (mData == null) {
mData = new JSONObject();
}
}

View file

@ -16,11 +16,6 @@
package com.google.android.vending.licensing;
import com.android.vending.licensing.ILicenseResultListener;
import com.android.vending.licensing.ILicensingService;
import com.google.android.vending.licensing.util.Base64;
import com.google.android.vending.licensing.util.Base64DecoderException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@ -31,6 +26,11 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import com.android.vending.licensing.ILicenseResultListener;
import com.android.vending.licensing.ILicensingService;
import com.google.android.vending.licensing.util.Base64;
import com.google.android.vending.licensing.util.Base64DecoderException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
@ -64,25 +64,23 @@ public class LicenseChecker implements ServiceConnection {
private static final SecureRandom RANDOM = new SecureRandom();
private static final boolean DEBUG_LICENSE_ERROR = false;
private ILicensingService mService;
private PublicKey mPublicKey;
private final PublicKey mPublicKey;
private final Context mContext;
private final Policy mPolicy;
/**
* A handler for running tasks on a background thread. We don't want license
* processing to block the UI thread.
*/
private Handler mHandler;
private final Handler mHandler;
private final String mPackageName;
private final String mVersionCode;
private final Set<LicenseValidator> mChecksInProgress = new HashSet<LicenseValidator>();
private final Queue<LicenseValidator> mPendingChecks = new LinkedList<LicenseValidator>();
private ILicensingService mService;
/**
* @param context a Context
* @param policy implementation of Policy
* @param context a Context
* @param policy implementation of Policy
* @param encodedPublicKey Base64-encoded RSA public key
* @throws IllegalArgumentException if encodedPublicKey is invalid
*/
@ -100,7 +98,7 @@ public class LicenseChecker implements ServiceConnection {
/**
* Generates a PublicKey instance from a string containing the
* Base64-encoded public key.
*
*
* @param encodedPublicKey Base64-encoded public key
* @throws IllegalArgumentException if encodedPublicKey is invalid
*/
@ -122,6 +120,23 @@ public class LicenseChecker implements ServiceConnection {
}
}
/**
* Get version code for the application package name.
*
* @param context
* @param packageName application package name
* @return the version code or empty string if package not found
*/
private static String getVersionCode(Context context, String packageName) {
try {
return String.valueOf(context.getPackageManager().getPackageInfo(packageName, 0).
versionCode);
} catch (NameNotFoundException e) {
// Log.e(TAG, "Package not found. could not get version code.");
return "";
}
}
/**
* Checks if the user should have access to the app. Binds the service if necessary.
* <p>
@ -131,6 +146,7 @@ public class LicenseChecker implements ServiceConnection {
* <p>
* source string: "com.android.vending.licensing.ILicensingService"
* <p>
*
* @param callback
*/
public synchronized void checkAccess(LicenseCheckerCallback callback) {
@ -145,8 +161,8 @@ public class LicenseChecker implements ServiceConnection {
if (mService == null) {
// Log.i(TAG, "Binding to licensing service.");
try {
String two = String.valueOf((new Date().getYear()+1900)/1000);
Intent serviceIntent = new Intent(new String(Base64.decode("Y" + two + "9tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY"+two+"Vuc"+two+"luZ1NlcnZpY"+two+"U=")));
String two = String.valueOf((new Date().getYear() + 1900) / 1000);
Intent serviceIntent = new Intent(new String(Base64.decode("Y" + two + "9tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY" + two + "Vuc" + two + "luZ1NlcnZpY" + two + "U=")));
serviceIntent.setPackage("com.android.vending");
boolean bindResult = mContext
.bindService(
@ -195,10 +211,88 @@ public class LicenseChecker implements ServiceConnection {
}
}
private class ResultListener extends ILicenseResultListener.Stub {
private final LicenseValidator mValidator;
private Runnable mOnTimeout;
public synchronized void onServiceConnected(ComponentName name, IBinder service) {
mService = ILicensingService.Stub.asInterface(service);
runChecks();
}
public synchronized void onServiceDisconnected(ComponentName name) {
// Called when the connection with the service has been
// unexpectedly disconnected. That is, Market crashed.
// If there are any checks in progress, the timeouts will handle them.
// Log.w(TAG, "Service unexpectedly disconnected.");
mService = null;
}
/**
* Generates policy response for service connection errors, as a result of
* disconnections or timeouts.
*/
private synchronized void handleServiceConnectionError(LicenseValidator validator) {
mPolicy.processServerResponse(Policy.RETRY, null);
if (mPolicy.allowAccess()) {
validator.getCallback().allow(Policy.RETRY);
} else {
validator.getCallback().dontAllow(Policy.RETRY);
}
}
/**
* Generates policy response for no service connection error (no Google Play service)
*/
private synchronized void handleNoServiceConnectionError(LicenseValidator validator) {
mPolicy.processServerResponse(Policy.NO_SERVICE, null);
if (mPolicy.allowAccess()) {
validator.getCallback().allow(Policy.NO_SERVICE);
} else {
validator.getCallback().dontAllow(Policy.NO_SERVICE);
}
}
/**
* Unbinds service if necessary and removes reference to it.
*/
private void cleanupService() {
if (mService != null) {
try {
mContext.unbindService(this);
} catch (IllegalArgumentException e) {
// Somehow we've already been unbound. This is a non-fatal
// error.
// Log.e(TAG, "Unable to unbind from licensing service (already unbound)");
}
mService = null;
}
}
/**
* Inform the library that the context is about to be destroyed, so that any
* open connections can be cleaned up.
* <p>
* Failure to call this method can result in a crash under certain
* circumstances, such as during screen rotation if an Activity requests the
* license check or when the user exits the application.
*/
public synchronized void onDestroy() {
cleanupService();
mHandler.getLooper().quit();
}
/**
* Generates a nonce (number used once).
*/
private int generateNonce() {
return RANDOM.nextInt();
}
private class ResultListener extends ILicenseResultListener.Stub {
private static final int ERROR_CONTACTING_SERVER = 0x101;
private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;
private static final int ERROR_NON_MATCHING_UID = 0x103;
private final LicenseValidator mValidator;
private final Runnable mOnTimeout;
public ResultListener(LicenseValidator validator) {
mValidator = validator;
mOnTimeout = new Runnable() {
@ -211,14 +305,10 @@ public class LicenseChecker implements ServiceConnection {
startTimeout();
}
private static final int ERROR_CONTACTING_SERVER = 0x101;
private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;
private static final int ERROR_NON_MATCHING_UID = 0x103;
// Runs in IPC thread pool. Post it to the Handler, so we can guarantee
// either this or the timeout runs.
public void verifyLicense(final int responseCode, final String signedData,
final String signature) {
final String signature) {
mHandler.post(new Runnable() {
public void run() {
// Log.i(TAG, "Received response.");
@ -272,93 +362,4 @@ public class LicenseChecker implements ServiceConnection {
mHandler.removeCallbacks(mOnTimeout);
}
}
public synchronized void onServiceConnected(ComponentName name, IBinder service) {
mService = ILicensingService.Stub.asInterface(service);
runChecks();
}
public synchronized void onServiceDisconnected(ComponentName name) {
// Called when the connection with the service has been
// unexpectedly disconnected. That is, Market crashed.
// If there are any checks in progress, the timeouts will handle them.
// Log.w(TAG, "Service unexpectedly disconnected.");
mService = null;
}
/**
* Generates policy response for service connection errors, as a result of
* disconnections or timeouts.
*/
private synchronized void handleServiceConnectionError(LicenseValidator validator) {
mPolicy.processServerResponse(Policy.RETRY, null);
if (mPolicy.allowAccess()) {
validator.getCallback().allow(Policy.RETRY);
} else {
validator.getCallback().dontAllow(Policy.RETRY);
}
}
/**
* Generates policy response for no service connection error (no Google Play service)
*/
private synchronized void handleNoServiceConnectionError(LicenseValidator validator) {
mPolicy.processServerResponse(Policy.NO_SERVICE, null);
if (mPolicy.allowAccess()) {
validator.getCallback().allow(Policy.NO_SERVICE);
} else {
validator.getCallback().dontAllow(Policy.NO_SERVICE);
}
}
/** Unbinds service if necessary and removes reference to it. */
private void cleanupService() {
if (mService != null) {
try {
mContext.unbindService(this);
} catch (IllegalArgumentException e) {
// Somehow we've already been unbound. This is a non-fatal
// error.
// Log.e(TAG, "Unable to unbind from licensing service (already unbound)");
}
mService = null;
}
}
/**
* Inform the library that the context is about to be destroyed, so that any
* open connections can be cleaned up.
* <p>
* Failure to call this method can result in a crash under certain
* circumstances, such as during screen rotation if an Activity requests the
* license check or when the user exits the application.
*/
public synchronized void onDestroy() {
cleanupService();
mHandler.getLooper().quit();
}
/** Generates a nonce (number used once). */
private int generateNonce() {
return RANDOM.nextInt();
}
/**
* Get version code for the application package name.
*
* @param context
* @param packageName application package name
* @return the version code or empty string if package not found
*/
private static String getVersionCode(Context context, String packageName) {
try {
return String.valueOf(context.getPackageManager().getPackageInfo(packageName, 0).
versionCode);
} catch (NameNotFoundException e) {
// Log.e(TAG, "Package not found. could not get version code.");
return "";
}
}
}

View file

@ -35,33 +35,35 @@ package com.google.android.vending.licensing;
public interface LicenseCheckerCallback {
/**
* Allow use. App should proceed as normal.
*
* @param reason Policy.LICENSED or Policy.RETRY typically. (although in
* theory the policy can return Policy.NOT_LICENSED here as well)
* Application error codes.
*/
public void allow(int reason);
int ERROR_INVALID_PACKAGE_NAME = 1;
int ERROR_NON_MATCHING_UID = 2;
int ERROR_NOT_MARKET_MANAGED = 3;
int ERROR_CHECK_IN_PROGRESS = 4;
int ERROR_INVALID_PUBLIC_KEY = 5;
int ERROR_MISSING_PERMISSION = 6;
/**
* Allow use. App should proceed as normal.
*
* @param reason Policy.LICENSED or Policy.RETRY typically. (although in
* theory the policy can return Policy.NOT_LICENSED here as well)
*/
void allow(int reason);
/**
* Don't allow use. App should inform user and take appropriate action.
*
*
* @param reason Policy.NOT_LICENSED or Policy.RETRY. (although in theory
* the policy can return Policy.LICENSED here as well ---
* perhaps the call to the LVL took too long, for example)
* the policy can return Policy.LICENSED here as well ---
* perhaps the call to the LVL took too long, for example)
*/
public void dontAllow(int reason);
/** Application error codes. */
public static final int ERROR_INVALID_PACKAGE_NAME = 1;
public static final int ERROR_NON_MATCHING_UID = 2;
public static final int ERROR_NOT_MARKET_MANAGED = 3;
public static final int ERROR_CHECK_IN_PROGRESS = 4;
public static final int ERROR_INVALID_PUBLIC_KEY = 5;
public static final int ERROR_MISSING_PERMISSION = 6;
void dontAllow(int reason);
/**
* Error in application code. Caller did not call or set up license checker
* correctly. Should be considered fatal.
*/
public void applicationError(int errorCode);
void applicationError(int errorCode);
}

View file

@ -30,29 +30,29 @@ public interface Policy {
/**
* LICENSED means that the server returned back a valid license response
*/
public static final int LICENSED = 0x16f8e94;
int LICENSED = 0x16f8e94;
/**
* NOT_LICENSED means that the server returned back a valid license response
* that indicated that the user definitively is not licensed
*/
public static final int NOT_LICENSED = 0x1;
int NOT_LICENSED = 0x1;
/**
* RETRY means that the license response was unable to be determined ---
* perhaps as a result of faulty networking
*/
public static final int RETRY = 0x56ee981;
int RETRY = 0x56ee981;
/**
* NO_SERVICE means no connection with the Google Play service
*/
public static final int NO_SERVICE = 0x936af1;
int NO_SERVICE = 0x936af1;
/**
* Provide results from contact with the license server. Retry counts are
* incremented if the current value of response is RETRY. Results will be
* used for any future policy decisions.
*
*
* @param response the result from validating the server response
* @param rawData the raw server response data, can be null for RETRY
* @param rawData the raw server response data, can be null for RETRY
*/
void processServerResponse(int response, ResponseData rawData);

View file

@ -16,17 +16,17 @@
package com.google.android.vending.licensing;
import android.content.Context;
import com.google.android.vending.licensing.util.Item;
import com.google.android.vending.licensing.util.URLUtils;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import com.google.android.vending.licensing.util.Item;
import com.google.android.vending.licensing.util.URLUtils;
/**
* Default policy. All policy decisions are based off of response data received
* from the licensing service. Specifically, the licensing server sends the
@ -54,14 +54,13 @@ public class ServerManagedPolicy implements Policy {
private static final String DEFAULT_RETRY_COUNT = "5";
private static final long MILLIS_PER_MINUTE = 60 * 1000;
private final JSONDataObfuscator mPreferences;
private long mValidityTimestamp;
private long mRetryUntil;
private long mMaxRetries;
private long mRetryCount;
private long mLastResponseTime = 0;
private int mLastResponse;
private JSONDataObfuscator mPreferences;
public ServerManagedPolicy(Context context) {
// Import old values
@ -86,7 +85,7 @@ public class ServerManagedPolicy implements Policy {
* </ul>
*
* @param response the result from validating the server response
* @param rawData the raw server response data
* @param rawData the raw server response data
*/
public void processServerResponse(int response, ResponseData rawData) {
@ -128,6 +127,10 @@ public class ServerManagedPolicy implements Policy {
mPreferences.putString(PREF_LAST_RESPONSE, Integer.toString(l));
}
public long getRetryCount() {
return mRetryCount;
}
/**
* Set the current retry count and add to preferences. You must manually
* call PreferenceObfuscator.commit() to commit these changes to disk.
@ -139,8 +142,8 @@ public class ServerManagedPolicy implements Policy {
mPreferences.putString(PREF_RETRY_COUNT, Long.toString(c));
}
public long getRetryCount() {
return mRetryCount;
public long getValidityTimestamp() {
return mValidityTimestamp;
}
/**
@ -165,8 +168,8 @@ public class ServerManagedPolicy implements Policy {
mPreferences.putString(PREF_VALIDITY_TIMESTAMP, validityTimestamp);
}
public long getValidityTimestamp() {
return mValidityTimestamp;
public long getRetryUntil() {
return mRetryUntil;
}
/**
@ -184,15 +187,15 @@ public class ServerManagedPolicy implements Policy {
// No response or not parsable, expire immediately
// Log.w(TAG, "License retry timestamp (GT) missing, grace period disabled");
retryUntil = "0";
lRetryUntil = 0l;
lRetryUntil = 0L;
}
mRetryUntil = lRetryUntil;
mPreferences.putString(PREF_RETRY_UNTIL, retryUntil);
}
public long getRetryUntil() {
return mRetryUntil;
public long getMaxRetries() {
return mMaxRetries;
}
/**
@ -210,20 +213,16 @@ public class ServerManagedPolicy implements Policy {
// No response or not parsable, expire immediately
// Log.w(TAG, "Licence retry count (GR) missing, grace period disabled");
maxRetries = "0";
lMaxRetries = 0l;
lMaxRetries = 0L;
}
mMaxRetries = lMaxRetries;
mPreferences.putString(PREF_MAX_RETRIES, maxRetries);
}
public long getMaxRetries() {
return mMaxRetries;
}
/**
* {@inheritDoc}
*
* <p>
* This implementation allows access if either:<br>
* <ol>
* <li>a LICENSED response was received within the validity period
@ -235,19 +234,14 @@ public class ServerManagedPolicy implements Policy {
long ts = System.currentTimeMillis();
if (mLastResponse == Policy.LICENSED) {
// Check if the LICENSED response occurred within the validity timeout.
if (ts <= mValidityTimestamp) {
// Cached LICENSED response is still valid.
return true;
}
// Cached LICENSED response is still valid.
return ts <= mValidityTimestamp;
} else if (mLastResponse == Policy.RETRY &&
ts < mLastResponseTime + MILLIS_PER_MINUTE) {
ts < mLastResponseTime + MILLIS_PER_MINUTE) {
// Only allow access if we are within the retry period or we haven't used up our
// max retries.
return (ts <= mRetryUntil || mRetryCount <= mMaxRetries);
} else if(mLastResponse == Policy.NO_SERVICE) {
return true;
}
return false;
} else return mLastResponse == Policy.NO_SERVICE;
}
private Map<String, String> decodeExtras(String extras) {

View file

@ -1,8 +1,8 @@
package com.google.android.vending.licensing.util;
public class Item {
private String name;
private String value;
private final String name;
private final String value;
public Item(String n, String v) {
name = n;

View file

@ -33,7 +33,6 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Process;
import android.view.View;
import android.widget.Toast;
@ -43,15 +42,15 @@ import com.google.android.vending.licensing.LicenseCheckerCallback;
import com.google.android.vending.licensing.Policy;
import com.google.android.vending.licensing.ServerManagedPolicy;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher_extreme.R;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.iab.IabHelper;
import net.pierrox.lightning_launcher.iab.IabResult;
import net.pierrox.lightning_launcher.iab.Inventory;
import net.pierrox.lightning_launcher.iab.Purchase;
import net.pierrox.lightning_launcher.prefs.LLPreference;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONException;
import org.json.JSONObject;
@ -67,11 +66,12 @@ public class LLAppExtreme extends LLAppPhone {
private static final String key4 = "hI3T9SPxlX4faIxSX0hwLJAtbb5IZWX5XvuQdQovF9W9";
private static final String key5 = "vRdURFT6D7K01k+doWbMDZnbfQXiYKHaaBja+SlsZA4UsHF6RubVTi+nOET1xBlpjNwQ6wl69GdM+y8WA1WR47JBNph6wuCF0q7pz2KbuBDvh5vSvYaBGb9dflqnOKy2S47DSA7HOwffTUtxilskp";
private static final String key6 = "JvKKBdyKwQoNTKyp7bjXUrFg/tlJOTo0je4RkcvBHiYCW/yEQKSPY43nlnapcy6L4P+0IV+GDHI+Zx1D+mPo6BmsTwIDAQAB";
private static final String LWP_PKG = "net.pierrox.lightning_launcher.lwp_key";
private static final String PATH_TEST = "t";
private static final String COLUMN_IS_LICENSED = "l";
private LicenseCheckerCallback mLicenseCheckerCallback;
private LicenseChecker mChecker;
private boolean mIsLicensed = true;
private IabHelper mIABHelper;
private String mIabKey;
private boolean mHasLWPIab;
@ -80,12 +80,12 @@ public class LLAppExtreme extends LLAppPhone {
@Override
public void onCreate() {
// obfuscation
String three = String.valueOf((new Date().getYear()+2901)/1000);
String three = String.valueOf((new Date().getYear() + 2901) / 1000);
mIabKey = key1 + three + key2;
mLicenseCheckerCallback = new MyLicenseCheckerCallback();
mIabKey += three + key3 + three + key4 + getString(R.string.internal_version);
mIabKey += three + key3 + three + key4 + getString(R.string.internal_version);
// obfuscation
mIabKey += key5 + three + key6;
@ -148,7 +148,7 @@ public class LLAppExtreme extends LLAppPhone {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.APP_STORE_INSTALL_PREFIX + context.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch(ActivityNotFoundException e) {
} catch (ActivityNotFoundException e) {
// pass
}
Toast.makeText(context, "Couldn't validate the Play Store license. Please check your internet connectivity.", Toast.LENGTH_LONG).show();
@ -171,33 +171,6 @@ public class LLAppExtreme extends LLAppPhone {
mChecker.checkAccess(mLicenseCheckerCallback);
}
private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
public void allow(int reason) {
mIsLicensed = true;
}
public void dontAllow(int reason) {
if (reason == Policy.RETRY) {
// If the reason received from the policy is RETRY, it was probably
// due to a loss of connection with the service, so we should give the
// user a chance to retry. So show a dialog to retry.
mIsLicensed = true;
} else {
// Otherwise, the user is not licensed to use this app.
// Your response should always inform the user that the application
// is not licensed, but your behavior at that point can vary. You might
// provide the user a limited access version of your app or you can
// take them to Google Play to purchase the app.
mIsLicensed = false;
}
}
@Override
public void applicationError(int errorCode) {
}
}
public String getIabKey() {
return mIabKey;
}
@ -221,28 +194,24 @@ public class LLAppExtreme extends LLAppPhone {
});
}
private static final String LWP_PKG = "net.pierrox.lightning_launcher.lwp_key";
private static final String PATH_TEST = "t";
private static final String COLUMN_IS_LICENSED = "l";
public void checkLwpKey() {
// first step : the permission is granted meaning the package is installed
mHasLWPKey = checkPermission(LWP_PKG, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED;
// second step, ask the key to check its license
new AsyncTask<Void,Void,Boolean>() {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... voids) {
boolean hasLicensedKey = false;
try {
Cursor c = getContentResolver().query(Uri.parse("content://"+LWP_PKG+"/" + PATH_TEST), new String[]{COLUMN_IS_LICENSED}, null, null, null);
Cursor c = getContentResolver().query(Uri.parse("content://" + LWP_PKG + "/" + PATH_TEST), new String[]{COLUMN_IS_LICENSED}, null, null, null);
if (c != null) {
c.moveToNext();
hasLicensedKey = c.getInt(0) == 1;
c.close();
}
} catch(Exception e) {
} catch (Exception e) {
// pass
}
return hasLicensedKey;
@ -251,14 +220,14 @@ public class LLAppExtreme extends LLAppPhone {
@Override
protected void onPostExecute(Boolean hasLicensedKey) {
// key is installed, but no license
if(mHasLWPKey && !hasLicensedKey) {
if (mHasLWPKey && !hasLicensedKey) {
LightningEngine engine = getAppEngine();
engine.getGlobalConfig().lwpScreen = Page.NONE;
engine.notifyGlobalConfigChanged();
}
mHasLWPKey = hasLicensedKey;
}
}.execute((Void)null);
}.execute((Void) null);
}
@ -271,12 +240,12 @@ public class LLAppExtreme extends LLAppPhone {
mHasLWPIab = false;
if(data.exists()) {
if (data.exists()) {
JSONObject o = FileUtils.readJSONObjectFromFile(data);
if(o != null) {
if (o != null) {
try {
mHasLWPIab = o.getBoolean(getString(R.string.iab_lwp));
} catch(JSONException e) {
} catch (JSONException e) {
// pass
}
}
@ -284,7 +253,7 @@ public class LLAppExtreme extends LLAppPhone {
}
public void setProductStatus(String sku, boolean purchased) {
if(sku.equals(getString(R.string.iab_lwp))) {
if (sku.equals(getString(R.string.iab_lwp))) {
mHasLWPIab = purchased;
}
File data = getUnlockInfoDataFile();
@ -297,10 +266,6 @@ public class LLAppExtreme extends LLAppPhone {
}
}
public interface UnlockResultReceiver {
void setUnlocked(String sku, boolean unlocked);
}
public void checkProducts(final UnlockResultReceiver receiver) {
// Have we been disposed of in the meantime? If so, quit.
if (mIABHelper == null || !mIABHelper.isSetupDone()) return;
@ -318,12 +283,12 @@ public class LLAppExtreme extends LLAppPhone {
Purchase lwp = inventory.getPurchase(iab_lwp);
boolean has_lwp = lwp != null /*&& verifyDeveloperPayload(unlock_pro)*/;
if(has_lwp) {
if (has_lwp) {
setProductStatus(iab_lwp, true);
if(receiver != null) receiver.setUnlocked(iab_lwp, true);
if (receiver != null) receiver.setUnlocked(iab_lwp, true);
} else {
setProductStatus(iab_lwp, false);
if(receiver != null) receiver.setUnlocked(iab_lwp, false);
if (receiver != null) receiver.setUnlocked(iab_lwp, false);
}
}
});
@ -341,7 +306,7 @@ public class LLAppExtreme extends LLAppPhone {
builder.setPositiveButton(context.getString(R.string.iab_y_key), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
context.startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse(Version.APP_STORE_INSTALL_PREFIX+"net.pierrox.lightning_launcher.lwp_key")), ""));
context.startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse(Version.APP_STORE_INSTALL_PREFIX + "net.pierrox.lightning_launcher.lwp_key")), ""));
}
});
builder.setNegativeButton(context.getString(R.string.iab_y_app), new DialogInterface.OnClickListener() {
@ -357,4 +322,31 @@ public class LLAppExtreme extends LLAppPhone {
private void startPurchaseProcess(Context context, String sku) {
PurchaseProcess.startActivity(context, sku);
}
public interface UnlockResultReceiver {
void setUnlocked(String sku, boolean unlocked);
}
private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
public void allow(int reason) {
mIsLicensed = true;
}
public void dontAllow(int reason) {
// If the reason received from the policy is RETRY, it was probably
// due to a loss of connection with the service, so we should give the
// user a chance to retry. So show a dialog to retry.
// Otherwise, the user is not licensed to use this app.
// Your response should always inform the user that the application
// is not licensed, but your behavior at that point can vary. You might
// provide the user a limited access version of your app or you can
// take them to Google Play to purchase the app.
mIsLicensed = reason == Policy.RETRY;
}
@Override
public void applicationError(int errorCode) {
}
}
}

View file

@ -39,133 +39,145 @@ package net.pierrox.lightning_launcher.iab;
* class.
*/
public class Base64 {
/** Specify encoding (value is {@code true}). */
/**
* Specify encoding (value is {@code true}).
*/
public final static boolean ENCODE = true;
/** Specify decoding (value is {@code false}). */
/**
* Specify decoding (value is {@code false}).
*/
public final static boolean DECODE = false;
/** The equals sign (=) as a byte. */
/**
* The equals sign (=) as a byte.
*/
private final static byte EQUALS_SIGN = (byte) '=';
/** The new line character (\n) as a byte. */
/**
* The new line character (\n) as a byte.
*/
private final static byte NEW_LINE = (byte) '\n';
/**
* The 64 valid Base64 values.
*/
private final static byte[] ALPHABET =
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
(byte) '9', (byte) '+', (byte) '/'};
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
(byte) '9', (byte) '+', (byte) '/'};
/**
* The 64 valid web safe Base64 values.
*/
private final static byte[] WEBSAFE_ALPHABET =
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
(byte) '9', (byte) '-', (byte) '_'};
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
(byte) '9', (byte) '-', (byte) '_'};
/**
* Translates a Base64 value to either its 6-bit reconstruction value
* or a negative number indicating some other meaning.
**/
private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
62, // Plus sign at decimal 43
-9, -9, -9, // Decimal 44 - 46
63, // Slash at decimal 47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, -9, -9, // Decimal 91 - 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-9, -9, -9, -9, -9 // Decimal 123 - 127
/* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
-5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
62, // Plus sign at decimal 43
-9, -9, -9, // Decimal 44 - 46
63, // Slash at decimal 47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, -9, -9, // Decimal 91 - 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-9, -9, -9, -9, -9 // Decimal 123 - 127
/* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
};
/** The web safe decodabet */
/**
* The web safe decodabet
*/
private final static byte[] WEBSAFE_DECODABET =
{-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44
62, // Dash '-' sign at decimal 45
-9, -9, // Decimal 46-47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, // Decimal 91-94
63, // Underscore '_' at decimal 95
-9, // Decimal 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-9, -9, -9, -9, -9 // Decimal 123 - 127
/* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
};
{-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44
62, // Dash '-' sign at decimal 45
-9, -9, // Decimal 46-47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, // Decimal 91-94
63, // Underscore '_' at decimal 95
-9, // Decimal 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-9, -9, -9, -9, -9 // Decimal 123 - 127
/* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
};
// Indicates white space in encoding
private final static byte WHITE_SPACE_ENC = -5;
// Indicates equals sign in encoding
private final static byte EQUALS_SIGN_ENC = -1;
/** Defeats instantiation. */
/**
* Defeats instantiation.
*/
private Base64() {
}
@ -184,17 +196,17 @@ public class Base64 {
* The actual number of significant bytes in your array is
* given by <var>numSigBytes</var>.
*
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param numSigBytes the number of significant bytes in your array
* @param destination the array to hold the conversion
* @param destOffset the index where output will be put
* @param alphabet is the encoding alphabet
* @param destOffset the index where output will be put
* @param alphabet is the encoding alphabet
* @return the <var>destination</var> array
* @since 1.3
*/
private static byte[] encode3to4(byte[] source, int srcOffset,
int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {
int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {
// 1 2 3
// 01234567890123456789012345678901 Bit position
// --------000000001111111122222222 Array position from threeBytes
@ -208,8 +220,8 @@ public class Base64 {
// when Java treats a value as negative that is cast from a byte to an int.
int inBuff =
(numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
switch (numSigBytes) {
case 3:
@ -250,9 +262,9 @@ public class Base64 {
/**
* Encodes a byte array into web safe Base64 notation.
*
* @param source The data to convert
* @param source The data to convert
* @param doPadding is {@code true} to pad result with '=' chars
* if it does not fall on 3 byte boundaries
* if it does not fall on 3 byte boundaries
*/
public static String encodeWebSafe(byte[] source, boolean doPadding) {
return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);
@ -261,22 +273,22 @@ public class Base64 {
/**
* Encodes a byte array into Base64 notation.
*
* @param source the data to convert
* @param off offset in array where conversion should begin
* @param len length of data to convert
* @param alphabet the encoding alphabet
* @param source the data to convert
* @param off offset in array where conversion should begin
* @param len length of data to convert
* @param alphabet the encoding alphabet
* @param doPadding is {@code true} to pad result with '=' chars
* if it does not fall on 3 byte boundaries
* if it does not fall on 3 byte boundaries
* @since 1.4
*/
public static String encode(byte[] source, int off, int len, byte[] alphabet,
boolean doPadding) {
boolean doPadding) {
byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);
int outLen = outBuff.length;
// If doPadding is false, set length to truncate '='
// padding characters
while (doPadding == false && outLen > 0) {
while (!doPadding && outLen > 0) {
if (outBuff[outLen - 1] != '=') {
break;
}
@ -289,19 +301,19 @@ public class Base64 {
/**
* Encodes a byte array into Base64 notation.
*
* @param source the data to convert
* @param off offset in array where conversion should begin
* @param len length of data to convert
* @param alphabet is the encoding alphabet
* @param source the data to convert
* @param off offset in array where conversion should begin
* @param len length of data to convert
* @param alphabet is the encoding alphabet
* @param maxLineLength maximum length of one line.
* @return the BASE64-encoded byte array
*/
public static byte[] encode(byte[] source, int off, int len, byte[] alphabet,
int maxLineLength) {
int maxLineLength) {
int lenDiv3 = (len + 2) / 3; // ceil(len / 3)
int len43 = lenDiv3 * 4;
byte[] outBuff = new byte[len43 // Main 4:3
+ (len43 / maxLineLength)]; // New lines
+ (len43 / maxLineLength)]; // New lines
int d = 0;
int e = 0;
@ -314,8 +326,8 @@ public class Base64 {
// but inlined for faster encoding (~20% improvement)
int inBuff =
((source[d + off] << 24) >>> 8)
| ((source[d + 1 + off] << 24) >>> 16)
| ((source[d + 2 + off] << 24) >>> 24);
| ((source[d + 1 + off] << 24) >>> 16)
| ((source[d + 2 + off] << 24) >>> 24);
outBuff[e] = alphabet[(inBuff >>> 18)];
outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f];
outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f];
@ -363,22 +375,21 @@ public class Base64 {
* This method returns the actual number of bytes that
* were converted from the Base64 encoding.
*
*
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param source the array to convert
* @param srcOffset the index where conversion begins
* @param destination the array to hold the conversion
* @param destOffset the index where output will be put
* @param decodabet the decodabet for decoding Base64 content
* @param destOffset the index where output will be put
* @param decodabet the decodabet for decoding Base64 content
* @return the number of decoded bytes converted
* @since 1.3
*/
private static int decode4to3(byte[] source, int srcOffset,
byte[] destination, int destOffset, byte[] decodabet) {
byte[] destination, int destOffset, byte[] decodabet) {
// Example: Dk==
if (source[srcOffset + 2] == EQUALS_SIGN) {
int outBuff =
((decodabet[source[srcOffset]] << 24) >>> 6)
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
destination[destOffset] = (byte) (outBuff >>> 16);
return 1;
@ -386,8 +397,8 @@ public class Base64 {
// Example: DkL=
int outBuff =
((decodabet[source[srcOffset]] << 24) >>> 6)
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
destination[destOffset] = (byte) (outBuff >>> 16);
destination[destOffset + 1] = (byte) (outBuff >>> 8);
@ -396,9 +407,9 @@ public class Base64 {
// Example: DkLE
int outBuff =
((decodabet[source[srcOffset]] << 24) >>> 6)
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
| ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
| ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
destination[destOffset] = (byte) (outBuff >> 16);
destination[destOffset + 1] = (byte) (outBuff >> 8);
@ -438,8 +449,8 @@ public class Base64 {
*
* @param source The Base64 encoded data
* @return decoded data
* @since 1.3
* @throws Base64DecoderException
* @since 1.3
*/
public static byte[] decode(byte[] source) throws Base64DecoderException {
return decode(source, 0, source.length);
@ -466,8 +477,8 @@ public class Base64 {
* @param off the offset of where to begin decoding
* @param len the length of characters to decode
* @return decoded data
* @since 1.3
* @throws Base64DecoderException
* @since 1.3
*/
public static byte[] decode(byte[] source, int off, int len)
throws Base64DecoderException {
@ -493,9 +504,9 @@ public class Base64 {
* Decodes Base64 content using the supplied decodabet and returns
* the decoded byte array.
*
* @param source the Base64 encoded data
* @param off the offset of where to begin decoding
* @param len the length of characters to decode
* @param source the Base64 encoded data
* @param off the offset of where to begin decoding
* @param len the length of characters to decode
* @param decodabet the decodabet for decoding Base64 content
* @return decoded data
*/

View file

@ -44,22 +44,22 @@ import java.util.List;
* It provides synchronous (blocking) and asynchronous (non-blocking) methods for
* many common in-app billing operations, as well as automatic signature
* verification.
*
* <p>
* After instantiating, you must perform setup in order to start using the object.
* To perform setup, call the {@link #startSetup} method and provide a listener;
* that listener will be notified when setup is complete, after which (and not before)
* you may call other methods.
*
* <p>
* After setup is complete, you will typically want to request an inventory of owned
* items and subscriptions. See {@link #queryInventory}, {@link #queryInventoryAsync}
* and related methods.
*
* <p>
* When you are done with this object, don't forget to call {@link #dispose}
* to ensure proper cleanup. This object holds a binding to the in-app billing
* service, which will leak unless you dispose of it correctly. If you created
* the object on an Activity's onCreate method, then the recommended
* place to dispose of it is the Activity's onDestroy method.
*
* <p>
* A note about threading: When using this object from a background thread, you may
* call the blocking versions of methods; when using from a UI thread, call
* only the asynchronous versions and handle the results via callbacks.
@ -68,47 +68,8 @@ import java.util.List;
* has not yet completed will result in an exception being thrown.
*
* @author Bruno Oliveira (Google)
*
*/
public class IabHelper {
// Is debug logging enabled?
boolean mDebugLog = false;
String mDebugTag = "IabHelper";
// Is setup done?
boolean mSetupDone = false;
// Has this object been disposed of? (If so, we should ignore callbacks, etc)
boolean mDisposed = false;
// Are subscriptions supported?
boolean mSubscriptionsSupported = false;
// Is an asynchronous operation in progress?
// (only one at a time can be in progress)
boolean mAsyncInProgress = false;
// (for logging/debugging)
// if mAsyncInProgress == true, what asynchronous operation is in progress?
String mAsyncOperation = "";
// Context we were passed during initialization
Context mContext;
// Connection to the service
IInAppBillingService mService;
ServiceConnection mServiceConn;
boolean mServiceBound;
// The request code used to launch purchase flow
int mRequestCode;
// The item type of the current purchase flow
String mPurchasingItemType;
// Public key for verifying signature, in base64 encoding
String mSignatureBase64 = null;
// Billing response codes
public static final int BILLING_RESPONSE_RESULT_OK = 0;
public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;
@ -118,7 +79,6 @@ public class IabHelper {
public static final int BILLING_RESPONSE_RESULT_ERROR = 6;
public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
// IAB Helper error codes
public static final int IABHELPER_ERROR_BASE = -1000;
public static final int IABHELPER_REMOTE_EXCEPTION = -1001;
@ -131,7 +91,6 @@ public class IabHelper {
public static final int IABHELPER_UNKNOWN_ERROR = -1008;
public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009;
public static final int IABHELPER_INVALID_CONSUMPTION = -1010;
// Keys for the responses from InAppBillingService
public static final String RESPONSE_CODE = "RESPONSE_CODE";
public static final String RESPONSE_GET_SKU_DETAILS_LIST = "DETAILS_LIST";
@ -142,25 +101,53 @@ public class IabHelper {
public static final String RESPONSE_INAPP_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST";
public static final String RESPONSE_INAPP_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST";
public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN";
// Item types
public static final String ITEM_TYPE_INAPP = "inapp";
public static final String ITEM_TYPE_SUBS = "subs";
// some fields on the getSkuDetails response bundle
public static final String GET_SKU_DETAILS_ITEM_LIST = "ITEM_ID_LIST";
public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = "ITEM_TYPE_LIST";
// Is debug logging enabled?
boolean mDebugLog = false;
String mDebugTag = "IabHelper";
// Is setup done?
boolean mSetupDone = false;
// Has this object been disposed of? (If so, we should ignore callbacks, etc)
boolean mDisposed = false;
// Are subscriptions supported?
boolean mSubscriptionsSupported = false;
// Is an asynchronous operation in progress?
// (only one at a time can be in progress)
boolean mAsyncInProgress = false;
// (for logging/debugging)
// if mAsyncInProgress == true, what asynchronous operation is in progress?
String mAsyncOperation = "";
// Context we were passed during initialization
Context mContext;
// Connection to the service
IInAppBillingService mService;
ServiceConnection mServiceConn;
boolean mServiceBound;
// The request code used to launch purchase flow
int mRequestCode;
// The item type of the current purchase flow
String mPurchasingItemType;
// Public key for verifying signature, in base64 encoding
String mSignatureBase64 = null;
// The listener registered on launchPurchaseFlow, which we have to call back when
// the purchase finishes
OnIabPurchaseFinishedListener mPurchaseListener;
/**
* Creates an instance. After creation, it will not yet be ready to use. You must perform
* setup by calling {@link #startSetup} and wait for setup to complete. This constructor does not
* block and is safe to call from a UI thread.
*
* @param ctx Your application or Activity context. Needed to bind to the in-app billing service.
* @param ctx Your application or Activity context. Needed to bind to the in-app billing service.
* @param base64PublicKey Your application's public key, encoded in base64.
* This is used for verification of purchase signatures. You can find your app's base64-encoded
* public key in your application's page on Google Play Developer Console. Note that this
* is NOT your "developer public key".
* This is used for verification of purchase signatures. You can find your app's base64-encoded
* public key in your application's page on Google Play Developer Console. Note that this
* is NOT your "developer public key".
*/
public IabHelper(Context ctx, String base64PublicKey) {
mContext = ctx.getApplicationContext();
@ -168,6 +155,39 @@ public class IabHelper {
logDebug("IAB helper created.");
}
/**
* Returns a human-readable description for the given response code.
*
* @param code The response code
* @return A human-readable string explaining the result code.
* It also includes the result code numerically.
*/
public static String getResponseDesc(int code) {
String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" +
"3:Billing Unavailable/4:Item unavailable/" +
"5:Developer Error/6:Error/7:Item Already Owned/" +
"8:Item not owned").split("/");
String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" +
"-1002:Bad response received/" +
"-1003:Purchase signature verification failed/" +
"-1004:Send intent failed/" +
"-1005:User cancelled/" +
"-1006:Unknown purchase response/" +
"-1007:Missing token/" +
"-1008:Unknown error/" +
"-1009:Subscriptions not available/" +
"-1010:Invalid consumption attempt").split("/");
if (code <= IABHELPER_ERROR_BASE) {
int index = IABHELPER_ERROR_BASE - code;
if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index];
else return code + ":Unknown IAB Helper Error";
} else if (code < 0 || code >= iab_msgs.length)
return code + ":Unknown";
else
return iab_msgs[code];
}
/**
* Enables or disable debug logging through LogCat.
*/
@ -182,19 +202,6 @@ public class IabHelper {
mDebugLog = enable;
}
/**
* Callback for setup process. This listener's {@link #onIabSetupFinished} method is called
* when the setup process is complete.
*/
public interface OnIabSetupFinishedListener {
/**
* Called to notify that setup is complete.
*
* @param result The result of the setup process.
*/
public void onIabSetupFinished(IabResult result);
}
/**
* Starts the setup process. This will start up the setup process asynchronously.
* You will be notified through the listener when the setup process is complete.
@ -225,9 +232,10 @@ public class IabHelper {
try {
logDebug("Checking for in-app billing 3 support.");
if(mService == null) {
if (listener != null) listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
"Error checking for billing v3 support, no service."));
if (mService == null) {
if (listener != null)
listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
"Error checking for billing v3 support, no service."));
// if in-app purchases aren't supported, neither are subscriptions.
mSubscriptionsSupported = false;
@ -251,17 +259,15 @@ public class IabHelper {
if (response == BILLING_RESPONSE_RESULT_OK) {
logDebug("Subscriptions AVAILABLE.");
mSubscriptionsSupported = true;
}
else {
} else {
logDebug("Subscriptions NOT AVAILABLE. Response: " + response);
}
mSetupDone = true;
}
catch (RemoteException e) {
} catch (RemoteException e) {
if (listener != null) {
listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION,
"RemoteException while setting up in-app billing."));
"RemoteException while setting up in-app billing."));
}
e.printStackTrace();
return;
@ -280,13 +286,12 @@ public class IabHelper {
// service available to handle that Intent
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
mServiceBound = true;
}
else {
} else {
// no service available to handle that Intent
if (listener != null) {
listener.onIabSetupFinished(
new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
"Billing service unavailable on device."));
"Billing service unavailable on device."));
}
}
}
@ -319,52 +324,34 @@ public class IabHelper {
}
private void checkNotDisposed() {
if (mDisposed) throw new IllegalStateException("IabHelper was disposed of, so it cannot be used.");
if (mDisposed)
throw new IllegalStateException("IabHelper was disposed of, so it cannot be used.");
}
/** Returns whether subscriptions are supported. */
/**
* Returns whether subscriptions are supported.
*/
public boolean subscriptionsSupported() {
checkNotDisposed();
return mSubscriptionsSupported;
}
/**
* Callback that notifies when a purchase is finished.
*/
public interface OnIabPurchaseFinishedListener {
/**
* Called to notify that an in-app purchase finished. If the purchase was successful,
* then the sku parameter specifies which item was purchased. If the purchase failed,
* the sku and extraData parameters may or may not be null, depending on how far the purchase
* process went.
*
* @param result The result of the purchase.
* @param info The purchase information (null if purchase failed)
*/
public void onIabPurchaseFinished(IabResult result, Purchase info);
}
// The listener registered on launchPurchaseFlow, which we have to call back when
// the purchase finishes
OnIabPurchaseFinishedListener mPurchaseListener;
public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
launchPurchaseFlow(act, sku, requestCode, listener, "");
}
public void launchPurchaseFlow(Activity act, String sku, int requestCode,
OnIabPurchaseFinishedListener listener, String extraData) {
OnIabPurchaseFinishedListener listener, String extraData) {
launchPurchaseFlow(act, sku, ITEM_TYPE_INAPP, requestCode, listener, extraData);
}
public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode,
OnIabPurchaseFinishedListener listener) {
OnIabPurchaseFinishedListener listener) {
launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, "");
}
public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode,
OnIabPurchaseFinishedListener listener, String extraData) {
OnIabPurchaseFinishedListener listener, String extraData) {
launchPurchaseFlow(act, sku, ITEM_TYPE_SUBS, requestCode, listener, extraData);
}
@ -376,18 +363,18 @@ public class IabHelper {
* this object's {@link #handleActivityResult} method to continue the purchase flow. This method
* MUST be called from the UI thread of the Activity.
*
* @param act The calling activity.
* @param sku The sku of the item to purchase.
* @param itemType indicates if it's a product or a subscription (ITEM_TYPE_INAPP or ITEM_TYPE_SUBS)
* @param act The calling activity.
* @param sku The sku of the item to purchase.
* @param itemType indicates if it's a product or a subscription (ITEM_TYPE_INAPP or ITEM_TYPE_SUBS)
* @param requestCode A request code (to differentiate from other responses --
* as in {@link Activity#startActivityForResult}).
* @param listener The listener to notify when the purchase process finishes
* @param extraData Extra data (developer payload), which will be returned with the purchase data
* when the purchase completes. This extra data will be permanently bound to that purchase
* and will always be returned when the purchase is queried.
* as in {@link Activity#startActivityForResult}).
* @param listener The listener to notify when the purchase process finishes
* @param extraData Extra data (developer payload), which will be returned with the purchase data
* when the purchase completes. This extra data will be permanently bound to that purchase
* and will always be returned when the purchase is queried.
*/
public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode,
OnIabPurchaseFinishedListener listener, String extraData) {
OnIabPurchaseFinishedListener listener, String extraData) {
checkNotDisposed();
checkSetupDone("launchPurchaseFlow");
flagStartAsync("launchPurchaseFlow");
@ -419,19 +406,17 @@ public class IabHelper {
mPurchaseListener = listener;
mPurchasingItemType = itemType;
act.startIntentSenderForResult(pendingIntent.getIntentSender(),
requestCode, new Intent(),
Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
}
catch (SendIntentException e) {
requestCode, new Intent(),
Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
} catch (SendIntentException e) {
logError("SendIntentException while launching purchase flow for sku " + sku);
e.printStackTrace();
flagEndAsync();
result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent.");
if (listener != null) listener.onIabPurchaseFinished(result, null);
}
catch (RemoteException e) {
} catch (RemoteException e) {
logError("RemoteException while launching purchase flow for sku " + sku);
e.printStackTrace();
flagEndAsync();
@ -448,11 +433,11 @@ public class IabHelper {
* MUST be called from the UI thread of the Activity.
*
* @param requestCode The requestCode as you received it.
* @param resultCode The resultCode as you received it.
* @param data The data (Intent) as you received it.
* @param resultCode The resultCode as you received it.
* @param data The data (Intent) as you received it.
* @return Returns true if the result was related to a purchase flow and was handled;
* false if the result was not related to a purchase, in which case you should
* handle it normally.
* false if the result was not related to a purchase, in which case you should
* handle it normally.
*/
public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result;
@ -486,7 +471,8 @@ public class IabHelper {
logError("BUG: either purchaseData or dataSignature is null.");
logDebug("Extras: " + data.getExtras().toString());
result = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
if (mPurchaseListener != null)
mPurchaseListener.onIabPurchaseFinished(result, null);
return true;
}
@ -499,38 +485,36 @@ public class IabHelper {
if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) {
logError("Purchase signature verification FAILED for sku " + sku);
result = new IabResult(IABHELPER_VERIFICATION_FAILED, "Signature verification failed for sku " + sku);
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, purchase);
if (mPurchaseListener != null)
mPurchaseListener.onIabPurchaseFinished(result, purchase);
return true;
}
logDebug("Purchase signature successfully verified.");
}
catch (JSONException e) {
} catch (JSONException e) {
logError("Failed to parse purchase data.");
e.printStackTrace();
result = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
if (mPurchaseListener != null)
mPurchaseListener.onIabPurchaseFinished(result, null);
return true;
}
if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Success"), purchase);
}
}
else if (resultCode == Activity.RESULT_OK) {
} else if (resultCode == Activity.RESULT_OK) {
// result code was OK, but in-app billing response was not OK.
logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode));
if (mPurchaseListener != null) {
result = new IabResult(responseCode, "Problem purchashing item.");
mPurchaseListener.onIabPurchaseFinished(result, null);
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
} else if (resultCode == Activity.RESULT_CANCELED) {
logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
}
else {
logError("Purchase failed. Result code: " + Integer.toString(resultCode)
} else {
logError("Purchase failed. Result code: " + resultCode
+ ". Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
@ -548,15 +532,15 @@ public class IabHelper {
* Do not call from a UI thread. For that, use the non-blocking version {@link #refreshInventoryAsync}.
*
* @param querySkuDetails if true, SKU details (price, description, etc) will be queried as well
* as purchase information.
* @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership.
* Ignored if null or if querySkuDetails is false.
* @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership.
* Ignored if null or if querySkuDetails is false.
* as purchase information.
* @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership.
* Ignored if null or if querySkuDetails is false.
* @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership.
* Ignored if null or if querySkuDetails is false.
* @throws IabException if a problem occurs while refreshing the inventory.
*/
public Inventory queryInventory(boolean querySkuDetails, List<String> moreItemSkus,
List<String> moreSubsSkus) throws IabException {
List<String> moreSubsSkus) throws IabException {
checkNotDisposed();
checkSetupDone("queryInventory");
try {
@ -589,29 +573,13 @@ public class IabHelper {
}
return inv;
}
catch (RemoteException e) {
} catch (RemoteException e) {
throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while refreshing inventory.", e);
}
catch (JSONException e) {
} catch (JSONException e) {
throw new IabException(IABHELPER_BAD_RESPONSE, "Error parsing JSON response while refreshing inventory.", e);
}
}
/**
* Listener that notifies when an inventory query operation completes.
*/
public interface QueryInventoryFinishedListener {
/**
* Called to notify that an inventory query operation completed.
*
* @param result The result of the operation.
* @param inv The inventory.
*/
public void onQueryInventoryFinished(IabResult result, Inventory inv);
}
/**
* Asynchronous wrapper for inventory query. This will perform an inventory
* query as described in {@link #queryInventory}, but will do so asynchronously
@ -619,12 +587,12 @@ public class IabHelper {
* call from a UI thread.
*
* @param querySkuDetails as in {@link #queryInventory}
* @param moreSkus as in {@link #queryInventory}
* @param listener The listener to notify when the refresh operation completes.
* @param moreSkus as in {@link #queryInventory}
* @param listener The listener to notify when the refresh operation completes.
*/
public void queryInventoryAsync(final boolean querySkuDetails,
final List<String> moreSkus,
final QueryInventoryFinishedListener listener) {
final List<String> moreSkus,
final QueryInventoryFinishedListener listener) {
final Handler handler = new Handler();
checkNotDisposed();
checkSetupDone("queryInventory");
@ -639,8 +607,7 @@ public class IabHelper {
Inventory inv = null;
try {
inv = queryInventory(querySkuDetails, moreSkus);
}
catch (IabException ex) {
} catch (IabException ex) {
result = ex.getResult();
}
@ -667,7 +634,6 @@ public class IabHelper {
queryInventoryAsync(querySkuDetails, null, listener);
}
/**
* Consumes a given in-app product. Consuming can only be done on an item
* that's owned, and as a result of consumption, the user will no longer own it.
@ -690,53 +656,24 @@ public class IabHelper {
String token = itemInfo.getToken();
String sku = itemInfo.getSku();
if (token == null || token.equals("")) {
logError("Can't consume "+ sku + ". No token.");
throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: "
+ sku + " " + itemInfo);
logError("Can't consume " + sku + ". No token.");
throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: "
+ sku + " " + itemInfo);
}
logDebug("Consuming sku: " + sku + ", token: " + token);
int response = mService.consumePurchase(3, mContext.getPackageName(), token);
if (response == BILLING_RESPONSE_RESULT_OK) {
logDebug("Successfully consumed sku: " + sku);
logDebug("Successfully consumed sku: " + sku);
} else {
logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response));
throw new IabException(response, "Error consuming sku " + sku);
}
else {
logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response));
throw new IabException(response, "Error consuming sku " + sku);
}
}
catch (RemoteException e) {
} catch (RemoteException e) {
throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while consuming. PurchaseInfo: " + itemInfo, e);
}
}
/**
* Callback that notifies when a consumption operation finishes.
*/
public interface OnConsumeFinishedListener {
/**
* Called to notify that a consumption has finished.
*
* @param purchase The purchase that was (or was to be) consumed.
* @param result The result of the consumption operation.
*/
public void onConsumeFinished(Purchase purchase, IabResult result);
}
/**
* Callback that notifies when a multi-item consumption operation finishes.
*/
public interface OnConsumeMultiFinishedListener {
/**
* Called to notify that a consumption of multiple items has finished.
*
* @param purchases The purchases that were (or were to be) consumed.
* @param results The results of each consumption operation, corresponding to each
* sku.
*/
public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);
}
/**
* Asynchronous wrapper to item consumption. Works like {@link #consume}, but
* performs the consumption in the background and notifies completion through
@ -755,8 +692,9 @@ public class IabHelper {
/**
* Same as {@link consumeAsync}, but for multiple items at once.
*
* @param purchases The list of PurchaseInfo objects representing the purchases to consume.
* @param listener The listener to notify when the consumption operation finishes.
* @param listener The listener to notify when the consumption operation finishes.
*/
public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) {
checkNotDisposed();
@ -764,41 +702,6 @@ public class IabHelper {
consumeAsyncInternal(purchases, null, listener);
}
/**
* Returns a human-readable description for the given response code.
*
* @param code The response code
* @return A human-readable string explaining the result code.
* It also includes the result code numerically.
*/
public static String getResponseDesc(int code) {
String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" +
"3:Billing Unavailable/4:Item unavailable/" +
"5:Developer Error/6:Error/7:Item Already Owned/" +
"8:Item not owned").split("/");
String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" +
"-1002:Bad response received/" +
"-1003:Purchase signature verification failed/" +
"-1004:Send intent failed/" +
"-1005:User cancelled/" +
"-1006:Unknown purchase response/" +
"-1007:Missing token/" +
"-1008:Unknown error/" +
"-1009:Subscriptions not available/" +
"-1010:Invalid consumption attempt").split("/");
if (code <= IABHELPER_ERROR_BASE) {
int index = IABHELPER_ERROR_BASE - code;
if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index];
else return String.valueOf(code) + ":Unknown IAB Helper Error";
}
else if (code < 0 || code >= iab_msgs.length)
return String.valueOf(code) + ":Unknown";
else
return iab_msgs[code];
}
// Checks that setup was done; if not, throws an exception.
void checkSetupDone(String operation) {
if (!mSetupDone) {
@ -813,9 +716,8 @@ public class IabHelper {
if (o == null) {
logDebug("Bundle with null response code, assuming OK (known issue)");
return BILLING_RESPONSE_RESULT_OK;
}
else if (o instanceof Integer) return ((Integer)o).intValue();
else if (o instanceof Long) return (int)((Long)o).longValue();
} else if (o instanceof Integer) return ((Integer) o).intValue();
else if (o instanceof Long) return (int) ((Long) o).longValue();
else {
logError("Unexpected type for bundle response code.");
logError(o.getClass().getName());
@ -829,9 +731,8 @@ public class IabHelper {
if (o == null) {
logError("Intent with no response code, assuming OK (known issue)");
return BILLING_RESPONSE_RESULT_OK;
}
else if (o instanceof Integer) return ((Integer)o).intValue();
else if (o instanceof Long) return (int)((Long)o).longValue();
} else if (o instanceof Integer) return ((Integer) o).intValue();
else if (o instanceof Long) return (int) ((Long) o).longValue();
else {
logError("Unexpected type for intent response code.");
logError(o.getClass().getName());
@ -853,7 +754,6 @@ public class IabHelper {
mAsyncInProgress = false;
}
int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException {
// Query purchases
logDebug("Querying owned items, item type: " + itemType);
@ -867,7 +767,7 @@ public class IabHelper {
itemType, continueToken);
int response = getResponseCodeFromBundle(ownedItems);
logDebug("Owned items response: " + String.valueOf(response));
logDebug("Owned items response: " + response);
if (response != BILLING_RESPONSE_RESULT_OK) {
logDebug("getPurchases() failed: " + getResponseDesc(response));
return response;
@ -880,11 +780,11 @@ public class IabHelper {
}
ArrayList<String> ownedSkus = ownedItems.getStringArrayList(
RESPONSE_INAPP_ITEM_LIST);
RESPONSE_INAPP_ITEM_LIST);
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(
RESPONSE_INAPP_PURCHASE_DATA_LIST);
RESPONSE_INAPP_PURCHASE_DATA_LIST);
ArrayList<String> signatureList = ownedItems.getStringArrayList(
RESPONSE_INAPP_SIGNATURE_LIST);
RESPONSE_INAPP_SIGNATURE_LIST);
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
@ -901,8 +801,7 @@ public class IabHelper {
// Record ownership and token
inv.addPurchase(purchase);
}
else {
} else {
logWarn("Purchase signature verification **FAILED**. Not adding item.");
logDebug(" Purchase data: " + purchaseData);
logDebug(" Signature: " + signature);
@ -918,7 +817,7 @@ public class IabHelper {
}
int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus)
throws RemoteException, JSONException {
throws RemoteException, JSONException {
logDebug("Querying SKU details.");
ArrayList<String> skuList = new ArrayList<String>();
skuList.addAll(inv.getAllOwnedSkus(itemType));
@ -945,8 +844,7 @@ public class IabHelper {
if (response != BILLING_RESPONSE_RESULT_OK) {
logDebug("getSkuDetails() failed: " + getResponseDesc(response));
return response;
}
else {
} else {
logError("getSkuDetails() returned a bundle with neither an error nor a detail list.");
return IABHELPER_BAD_RESPONSE;
}
@ -963,7 +861,6 @@ public class IabHelper {
return BILLING_RESPONSE_RESULT_OK;
}
void consumeAsyncInternal(final List<Purchase> purchases,
final OnConsumeFinishedListener singleListener,
final OnConsumeMultiFinishedListener multiListener) {
@ -976,8 +873,7 @@ public class IabHelper {
try {
consume(purchase);
results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, "Successful consume of sku " + purchase.getSku()));
}
catch (IabException ex) {
} catch (IabException ex) {
results.add(ex.getResult());
}
}
@ -1012,4 +908,74 @@ public class IabHelper {
void logWarn(String msg) {
Log.w(mDebugTag, "In-app billing warning: " + msg);
}
/**
* Callback for setup process. This listener's {@link #onIabSetupFinished} method is called
* when the setup process is complete.
*/
public interface OnIabSetupFinishedListener {
/**
* Called to notify that setup is complete.
*
* @param result The result of the setup process.
*/
void onIabSetupFinished(IabResult result);
}
/**
* Callback that notifies when a purchase is finished.
*/
public interface OnIabPurchaseFinishedListener {
/**
* Called to notify that an in-app purchase finished. If the purchase was successful,
* then the sku parameter specifies which item was purchased. If the purchase failed,
* the sku and extraData parameters may or may not be null, depending on how far the purchase
* process went.
*
* @param result The result of the purchase.
* @param info The purchase information (null if purchase failed)
*/
void onIabPurchaseFinished(IabResult result, Purchase info);
}
/**
* Listener that notifies when an inventory query operation completes.
*/
public interface QueryInventoryFinishedListener {
/**
* Called to notify that an inventory query operation completed.
*
* @param result The result of the operation.
* @param inv The inventory.
*/
void onQueryInventoryFinished(IabResult result, Inventory inv);
}
/**
* Callback that notifies when a consumption operation finishes.
*/
public interface OnConsumeFinishedListener {
/**
* Called to notify that a consumption has finished.
*
* @param purchase The purchase that was (or was to be) consumed.
* @param result The result of the consumption operation.
*/
void onConsumeFinished(Purchase purchase, IabResult result);
}
/**
* Callback that notifies when a multi-item consumption operation finishes.
*/
public interface OnConsumeMultiFinishedListener {
/**
* Called to notify that a consumption of multiple items has finished.
*
* @param purchases The purchases that were (or were to be) consumed.
* @param results The results of each consumption operation, corresponding to each
* sku.
*/
void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);
}
}

View file

@ -25,27 +25,36 @@ import java.util.Map;
* An Inventory is returned by such methods as {@link IabHelper#queryInventory}.
*/
public class Inventory {
Map<String,SkuDetails> mSkuMap = new HashMap<String,SkuDetails>();
Map<String,Purchase> mPurchaseMap = new HashMap<String,Purchase>();
Map<String, SkuDetails> mSkuMap = new HashMap<String, SkuDetails>();
Map<String, Purchase> mPurchaseMap = new HashMap<String, Purchase>();
Inventory() { }
Inventory() {
}
/** Returns the listing details for an in-app product. */
/**
* Returns the listing details for an in-app product.
*/
public SkuDetails getSkuDetails(String sku) {
return mSkuMap.get(sku);
}
/** Returns purchase information for a given product, or null if there is no purchase. */
/**
* Returns purchase information for a given product, or null if there is no purchase.
*/
public Purchase getPurchase(String sku) {
return mPurchaseMap.get(sku);
}
/** Returns whether or not there exists a purchase of the given product. */
/**
* Returns whether or not there exists a purchase of the given product.
*/
public boolean hasPurchase(String sku) {
return mPurchaseMap.containsKey(sku);
}
/** Return whether or not details about the given product are available. */
/**
* Return whether or not details about the given product are available.
*/
public boolean hasDetails(String sku) {
return mSkuMap.containsKey(sku);
}
@ -59,15 +68,19 @@ public class Inventory {
* a new Inventory.
*/
public void erasePurchase(String sku) {
if (mPurchaseMap.containsKey(sku)) mPurchaseMap.remove(sku);
mPurchaseMap.remove(sku);
}
/** Returns a list of all owned product IDs. */
/**
* Returns a list of all owned product IDs.
*/
List<String> getAllOwnedSkus() {
return new ArrayList<String>(mPurchaseMap.keySet());
}
/** Returns a list of all owned product IDs of a given type */
/**
* Returns a list of all owned product IDs of a given type
*/
List<String> getAllOwnedSkus(String itemType) {
List<String> result = new ArrayList<String>();
for (Purchase p : mPurchaseMap.values()) {
@ -76,7 +89,9 @@ public class Inventory {
return result;
}
/** Returns a list of all purchases. */
/**
* Returns a list of all purchases.
*/
List<Purchase> getAllPurchases() {
return new ArrayList<Purchase>(mPurchaseMap.values());
}

View file

@ -16,13 +16,7 @@
package com.boombuler.system.appwidgetpicker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.annotation.TargetApi;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
@ -37,56 +31,61 @@ import android.view.Window;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.activities.ResourceWrapperActivity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class AppWidgetPickerActivity extends ResourceWrapperActivity {
private static final int REQUEST_BIND_APPWIDGET = 1;
private Intent fIntent = null;
private PackageManager fPManager = null;
private AppWidgetManager fAppWManager = null;
private ArrayList<SubItem> fItems;
private int fAppWidgetId;
private Intent fIntent = null;
private PackageManager fPManager = null;
private AppWidgetManager fAppWManager = null;
private ArrayList<SubItem> fItems;
private int fAppWidgetId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitle("");
requestWindowFeature(Window.FEATURE_NO_TITLE);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitle("");
requestWindowFeature(Window.FEATURE_NO_TITLE);
fIntent = getIntent();
fIntent = getIntent();
final Intent intent = getIntent();
final Intent intent = getIntent();
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
fAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
fPManager = getPackageManager();
fAppWManager = AppWidgetManager.getInstance(this);
fAppWManager = AppWidgetManager.getInstance(this);
fItems = new ArrayList<SubItem>();
AddAppWidgetProviderInfos();
AddCustomAppWidgets();
Collections.sort(fItems, new Comparator<SubItem>() {
fItems = new ArrayList<SubItem>();
AddAppWidgetProviderInfos();
AddCustomAppWidgets();
Collections.sort(fItems, new Comparator<SubItem>() {
@Override
public int compare(SubItem object1, SubItem object2) {
return object1.getName().compareToIgnoreCase(object2.getName());
}
@Override
public int compare(SubItem object1, SubItem object2) {
return object1.getName().compareToIgnoreCase(object2.getName());
}
});
for(SubItem itm : fItems) {
if (itm instanceof Item) {
((Item)itm).sort();
}
}
new PickWidgetDialog(this).showDialog(null);
});
for (SubItem itm : fItems) {
if (itm instanceof Item) {
((Item) itm).sort();
}
}
new PickWidgetDialog(this).showDialog(null);
} else {
finish();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_BIND_APPWIDGET) {
if(resultCode == RESULT_OK) {
if (requestCode == REQUEST_BIND_APPWIDGET) {
if (resultCode == RESULT_OK) {
setResult(RESULT_OK);
} else {
LLApp.get().getAppWidgetHost().deleteAppWidgetId(fAppWidgetId);
@ -98,11 +97,11 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
}
public ArrayList<SubItem> getItems() {
return fItems;
}
return fItems;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void finishOk(SubItem item) {
int result;
if (item.getExtra() != null) {
@ -111,7 +110,7 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
setResult(RESULT_OK, getIntent(item));
} else {
try {
if(fAppWManager.bindAppWidgetIdIfAllowed(fAppWidgetId, item.getProvider())) {
if (fAppWManager.bindAppWidgetIdIfAllowed(fAppWidgetId, item.getProvider())) {
result = RESULT_OK;
} else {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
@ -131,15 +130,15 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
setResult(result, fIntent);
}
finish();
}
}
/**
/**
* Build the {@link Intent} described by this item. If this item
* can't create a valid {@link ComponentName}, it will return
* {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label.
*/
private Intent getIntent(SubItem itm) {
Intent intent = null;
Intent intent = null;
Parcelable parcel = fIntent.getParcelableExtra(Intent.EXTRA_INTENT);
if (parcel instanceof Intent) {
intent = new Intent((Intent) parcel);
@ -162,47 +161,43 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
return intent;
}
private Item getPackageItem(AppWidgetProviderInfo info) {
String packName = info.provider.getPackageName();
for (SubItem itm : fItems) {
if (itm instanceof Item) {
Item i = (Item)itm;
if (i.getPackageName().equals(packName)) {
return i;
}
}
}
try
{
android.content.pm.ApplicationInfo appInfo = fPManager.getApplicationInfo(info.provider.getPackageName(), 0);
Drawable appIcon = fPManager.getApplicationIcon(appInfo);
CharSequence str = fPManager.getApplicationLabel(appInfo);
Item newItm = new Item(str.toString(), appIcon);
newItm.setPackageName(packName);
fItems.add(newItm);
return newItm;
}
catch(PackageManager.NameNotFoundException expt) {
}
return null;
}
private Item getPackageItem(AppWidgetProviderInfo info) {
String packName = info.provider.getPackageName();
for (SubItem itm : fItems) {
if (itm instanceof Item) {
Item i = (Item) itm;
if (i.getPackageName().equals(packName)) {
return i;
}
}
}
try {
android.content.pm.ApplicationInfo appInfo = fPManager.getApplicationInfo(info.provider.getPackageName(), 0);
Drawable appIcon = fPManager.getApplicationIcon(appInfo);
CharSequence str = fPManager.getApplicationLabel(appInfo);
Item newItm = new Item(str.toString(), appIcon);
newItm.setPackageName(packName);
fItems.add(newItm);
return newItm;
} catch (PackageManager.NameNotFoundException expt) {
}
return null;
}
private void AddAppWidgetProviderInfos() {
List<AppWidgetProviderInfo> infos = fAppWManager.getInstalledProviders();
private void AddAppWidgetProviderInfos() {
List<AppWidgetProviderInfo> infos = fAppWManager.getInstalledProviders();
for(AppWidgetProviderInfo info : infos) {
try
{
android.content.pm.ApplicationInfo appInfo = fPManager.getApplicationInfo(info.provider.getPackageName(), 0);
SubItem itm = new SubItem(info.label, fPManager.getDrawable(info.provider.getPackageName(), info.icon, appInfo));
itm.setProvider(info.provider);
Item mainItm = getPackageItem(info);
mainItm.getItems().add(itm);
}
catch(PackageManager.NameNotFoundException expt) {
}
}
}
for (AppWidgetProviderInfo info : infos) {
try {
android.content.pm.ApplicationInfo appInfo = fPManager.getApplicationInfo(info.provider.getPackageName(), 0);
SubItem itm = new SubItem(info.label, fPManager.getDrawable(info.provider.getPackageName(), info.icon, appInfo));
itm.setProvider(info.provider);
Item mainItm = getPackageItem(info);
mainItm.getItems().add(itm);
} catch (PackageManager.NameNotFoundException expt) {
}
}
}
private void AddCustomAppWidgets() {
final Bundle extras = fIntent.getExtras();
@ -210,7 +205,8 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
// get and validate the extras they gave us
ArrayList<AppWidgetProviderInfo> customInfo = null;
ArrayList<Bundle> customExtras = null;
try_custom_items: {
try_custom_items:
{
customInfo = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_INFO);
if (customInfo == null || customInfo.size() == 0) {
@ -218,7 +214,7 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
}
int customInfoSize = customInfo.size();
for (int i=0; i<customInfoSize; i++) {
for (int i = 0; i < customInfoSize; i++) {
Parcelable p = customInfo.get(i);
if (p == null || !(p instanceof AppWidgetProviderInfo)) {
customInfo = null;
@ -235,7 +231,7 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
if (customInfoSize != customExtrasSize) {
break try_custom_items;
}
for (int i=0; i<customExtrasSize; i++) {
for (int i = 0; i < customExtrasSize; i++) {
Parcelable p = customExtras.get(i);
if (p == null || !(p instanceof Bundle)) {
customInfo = null;
@ -248,13 +244,13 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
}
private void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets, List<Bundle> customExtras) {
if (appWidgets == null)
return;
if (appWidgets == null)
return;
final int size = appWidgets.size();
for (int i = 0; i < size; i++) {
AppWidgetProviderInfo info = appWidgets.get(i);
String label = info.label.toString();
String label = info.label;
Drawable icon = null;
if (info.icon != 0) {
@ -267,7 +263,7 @@ public class AppWidgetPickerActivity extends ResourceWrapperActivity {
item.setPackageName(info.provider.getPackageName());
if (customExtras != null) {
subItem.setExtra(customExtras.get(i));
subItem.setExtra(customExtras.get(i));
}
fItems.add(item);

View file

@ -15,8 +15,6 @@
*/
package com.boombuler.system.appwidgetpicker;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@ -27,49 +25,48 @@ import android.widget.TextView;
import net.pierrox.lightning_launcher_extreme.R;
import java.util.ArrayList;
public class ItemAdapter extends ArrayAdapter<SubItem> {
private final ArrayList<SubItem> items;
private final Context fContext;
private final ArrayList<SubItem> items;
private final Context fContext;
public ItemAdapter(Context context, int textViewResourceId, ArrayList<SubItem> items) {
public ItemAdapter(Context context, int textViewResourceId, ArrayList<SubItem> items) {
super(context, textViewResourceId, items);
this.items = items;
fContext = context;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)fContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater vi = (LayoutInflater) fContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.appwidgetpicker, null);
}
SubItem o = items.get(position);
v.setTag(o);
if (o != null) {
TextView tv = (TextView) v.findViewById(R.id.appwidgetpicker_textview);
TextView count_view = (TextView) v.findViewById(R.id.appwidgetpicker_count);
ImageView iv = (ImageView) v.findViewById(R.id.appwidgetpicker_imageview);
TextView tv = v.findViewById(R.id.appwidgetpicker_textview);
TextView count_view = v.findViewById(R.id.appwidgetpicker_count);
ImageView iv = v.findViewById(R.id.appwidgetpicker_imageview);
if (tv != null) {
tv.setText(o.getName());
tv.setText(o.getName());
}
if (count_view != null) {
if (o instanceof Item)
{
int cnt = ((Item)o).getItems().size();
if (cnt > 1) {
count_view.setText(String.format(fContext.getString(R.string.widget_count), cnt));
count_view.setVisibility(View.VISIBLE);
}
else
count_view.setVisibility(View.GONE);
}
else
count_view.setVisibility(View.GONE);
if (o instanceof Item) {
int cnt = ((Item) o).getItems().size();
if (cnt > 1) {
count_view.setText(String.format(fContext.getString(R.string.widget_count), cnt));
count_view.setVisibility(View.VISIBLE);
} else
count_view.setVisibility(View.GONE);
} else
count_view.setVisibility(View.GONE);
}
if(iv != null){
iv.setImageDrawable(o.getImage());
if (iv != null) {
iv.setImageDrawable(o.getImage());
}
}
return v;

View file

@ -20,35 +20,38 @@ import android.content.ComponentName;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
public class SubItem {
private String fName;
private Drawable fImage;
public Bundle fExtra = null;
public ComponentName fProvider = null;
public SubItem(String name, Drawable image) {
fName = name;
fImage = image;
}
public void setExtra(Bundle aValue) {
fExtra = aValue;
}
public Bundle getExtra() {
return fExtra;
}
public void setProvider(ComponentName aValue) {
fProvider = aValue;
}
public ComponentName getProvider() {
return fProvider;
}
public String getName() {
return fName;
}
public Drawable getImage() {
return fImage;
}
public class SubItem {
private final String fName;
private final Drawable fImage;
public Bundle fExtra = null;
public ComponentName fProvider = null;
public SubItem(String name, Drawable image) {
fName = name;
fImage = image;
}
public Bundle getExtra() {
return fExtra;
}
public void setExtra(Bundle aValue) {
fExtra = aValue;
}
public ComponentName getProvider() {
return fProvider;
}
public void setProvider(ComponentName aValue) {
fProvider = aValue;
}
public String getName() {
return fName;
}
public Drawable getImage() {
return fImage;
}
}

View file

@ -18,116 +18,117 @@ import com.google.android.hotword.service.IHotwordService;
@TargetApi(Build.VERSION_CODES.KITKAT)
public class HotwordServiceClient {
@SuppressWarnings("unused")
private static final boolean DBG = false;
private static final String HOTWORD_SERVICE = "com.google.android.googlequicksearchbox.HOTWORD_SERVICE";
private static final String TAG = "HotwordServiceClient";
private static final String VEL_PACKAGE = "com.google.android.googlequicksearchbox";
@SuppressWarnings("unused")
private static final boolean DBG = false;
private static final String HOTWORD_SERVICE = "com.google.android.googlequicksearchbox.HOTWORD_SERVICE";
private static final String TAG = "HotwordServiceClient";
private static final String VEL_PACKAGE = "com.google.android.googlequicksearchbox";
private final Activity mActivity;
private final ServiceConnection mConnection;
private final WindowId.FocusObserver mFocusObserver;
private final Activity mActivity;
private final ServiceConnection mConnection;
private final WindowId.FocusObserver mFocusObserver;
private IHotwordService mHotwordService;
private IHotwordService mHotwordService;
private boolean mHotwordStart;
private boolean mIsAvailable = true;
private boolean mIsBound;
private boolean mIsFocused = false;
private boolean mIsRequested = true;
private boolean mHotwordStart;
private boolean mIsAvailable = true;
private boolean mIsBound;
private boolean mIsFocused = false;
private boolean mIsRequested = true;
public HotwordServiceClient(Activity activity) {
mActivity = activity;
mConnection = new HotwordServiceConnection();
mFocusObserver = new WindowFocusObserver();
}
public HotwordServiceClient(Activity activity) {
mActivity = activity;
mConnection = new HotwordServiceConnection();
mFocusObserver = new WindowFocusObserver();
}
private void assertMainThread() {
if (Looper.getMainLooper().getThread() != Thread.currentThread())
throw new IllegalStateException("Must be called on the main thread.");
}
private void assertMainThread() {
if (Looper.getMainLooper().getThread() != Thread.currentThread())
throw new IllegalStateException("Must be called on the main thread.");
}
private void internalBind() {
if (!mIsAvailable || mIsBound) {
if (!mIsAvailable)
Log.w(TAG, "Hotword service is not available.");
return;
}
private void internalBind() {
if (!mIsAvailable || mIsBound) {
if (!mIsAvailable)
Log.w(TAG, "Hotword service is not available.");
return;
}
Intent localIntent = new Intent(HOTWORD_SERVICE).setPackage(VEL_PACKAGE);
mIsAvailable = mActivity.bindService(localIntent, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = mIsAvailable;
}
Intent localIntent = new Intent(HOTWORD_SERVICE).setPackage(VEL_PACKAGE);
mIsAvailable = mActivity.bindService(localIntent, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = mIsAvailable;
}
private void internalRequestHotword() {
if (mIsFocused && mIsRequested) {
if (!mHotwordStart) {
mHotwordStart = true;
if (!mIsBound) {
internalBind();
}
}
}
private void internalRequestHotword() {
if (mIsFocused && mIsRequested) {
if (!mHotwordStart) {
mHotwordStart = true;
if (!mIsBound) {
internalBind();
}
}
}
try {
if (mHotwordService != null)
mHotwordService.requestHotwordDetection(mActivity.getPackageName(), mIsFocused && mIsRequested);
} catch (RemoteException e) {
Log.w(TAG, "requestHotwordDetection - remote call failed", e);
return;
}
}
try {
if (mHotwordService != null)
mHotwordService.requestHotwordDetection(mActivity.getPackageName(), mIsFocused && mIsRequested);
} catch (RemoteException e) {
Log.w(TAG, "requestHotwordDetection - remote call failed", e);
}
}
public final void onAttachedToWindow() {
assertMainThread();
mActivity.getWindow().getDecorView().getWindowId().registerFocusObserver(mFocusObserver);
internalBind();
}
public final void onAttachedToWindow() {
assertMainThread();
mActivity.getWindow().getDecorView().getWindowId().registerFocusObserver(mFocusObserver);
internalBind();
}
@SuppressLint("MissingSuperCall")
public final void onDetachedFromWindow() {
if (!mIsBound) {
return;
}
@SuppressLint("MissingSuperCall")
public final void onDetachedFromWindow() {
if (!mIsBound) {
return;
}
assertMainThread();
mActivity.getWindow().getDecorView().getWindowId().unregisterFocusObserver(mFocusObserver);
mActivity.unbindService(mConnection);
mIsBound = false;
}
assertMainThread();
mActivity.getWindow().getDecorView().getWindowId().unregisterFocusObserver(mFocusObserver);
mActivity.unbindService(mConnection);
mIsBound = false;
}
public final void requestHotwordDetection(boolean detect) {
assertMainThread();
mIsRequested = detect;
internalRequestHotword();
}
public final void requestHotwordDetection(boolean detect) {
assertMainThread();
mIsRequested = detect;
internalRequestHotword();
}
private class HotwordServiceConnection implements ServiceConnection {
private HotwordServiceConnection() {}
private class HotwordServiceConnection implements ServiceConnection {
private HotwordServiceConnection() {
}
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mHotwordService = IHotwordService.Stub.asInterface(iBinder);
internalRequestHotword();
}
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mHotwordService = IHotwordService.Stub.asInterface(iBinder);
internalRequestHotword();
}
public void onServiceDisconnected(ComponentName componentName) {
mIsBound = false;
mHotwordService = null;
}
}
public void onServiceDisconnected(ComponentName componentName) {
mIsBound = false;
mHotwordService = null;
}
}
private class WindowFocusObserver extends WindowId.FocusObserver {
private WindowFocusObserver() {}
private class WindowFocusObserver extends WindowId.FocusObserver {
private WindowFocusObserver() {
}
public void onFocusGained(WindowId wid) {
mIsFocused = true;
internalRequestHotword();
}
public void onFocusGained(WindowId wid) {
mIsFocused = true;
internalRequestHotword();
}
public void onFocusLost(WindowId wid) {
mIsFocused = false;
internalRequestHotword();
}
}
public void onFocusLost(WindowId wid) {
mIsFocused = false;
internalRequestHotword();
}
}
}

View file

@ -6,72 +6,72 @@ import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
public abstract interface IHotwordService extends IInterface {
public abstract void requestHotwordDetection(String packageName, boolean detect) throws RemoteException;
public interface IHotwordService extends IInterface {
void requestHotwordDetection(String packageName, boolean detect) throws RemoteException;
public static abstract class Stub extends Binder implements IHotwordService {
private static final String DESCRIPTOR = "com.google.android.hotword.service.IHotwordService";
static final int TRANSACTION_requestHotwordDetection = 1;
abstract class Stub extends Binder implements IHotwordService {
static final int TRANSACTION_requestHotwordDetection = 1;
private static final String DESCRIPTOR = "com.google.android.hotword.service.IHotwordService";
public Stub() {
attachInterface(this, DESCRIPTOR);
}
public Stub() {
attachInterface(this, DESCRIPTOR);
}
public static IHotwordService asInterface(IBinder binder) {
if (binder == null)
return null;
IInterface iInterface = binder.queryLocalInterface(DESCRIPTOR);
if (iInterface != null && iInterface instanceof IHotwordService)
return (IHotwordService)iInterface;
return new Proxy(binder);
}
public static IHotwordService asInterface(IBinder binder) {
if (binder == null)
return null;
IInterface iInterface = binder.queryLocalInterface(DESCRIPTOR);
if (iInterface != null && iInterface instanceof IHotwordService)
return (IHotwordService) iInterface;
return new Proxy(binder);
}
public IBinder asBinder() {
return this;
}
public IBinder asBinder() {
return this;
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
default:
return super.onTransact(code, data, reply, flags);
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_requestHotwordDetection:
data.enforceInterface(DESCRIPTOR);
String packageName = data.readString();
boolean detect = (data.readInt() == 1) ? true : false;
requestHotwordDetection(packageName, detect);
return true;
}
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
default:
return super.onTransact(code, data, reply, flags);
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_requestHotwordDetection:
data.enforceInterface(DESCRIPTOR);
String packageName = data.readString();
boolean detect = data.readInt() == 1;
requestHotwordDetection(packageName, detect);
return true;
}
}
private static class Proxy implements IHotwordService {
private IBinder mRemote;
private static class Proxy implements IHotwordService {
private final IBinder mRemote;
Proxy(IBinder iBinder) {
mRemote = iBinder;
}
Proxy(IBinder iBinder) {
mRemote = iBinder;
}
public IBinder asBinder() {
return mRemote;
}
public IBinder asBinder() {
return mRemote;
}
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
public String getInterfaceDescriptor() {
return DESCRIPTOR;
}
public void requestHotwordDetection(String packageName, boolean detect) throws RemoteException {
Parcel data = Parcel.obtain();
try {
data.writeInterfaceToken(getInterfaceDescriptor());
data.writeString(packageName);
data.writeInt(detect ? 1 : 0);
mRemote.transact(TRANSACTION_requestHotwordDetection, data, null, FLAG_ONEWAY);
} finally {
data.recycle();
}
}
}
}
public void requestHotwordDetection(String packageName, boolean detect) throws RemoteException {
Parcel data = Parcel.obtain();
try {
data.writeInterfaceToken(getInterfaceDescriptor());
data.writeString(packageName);
data.writeInt(detect ? 1 : 0);
mRemote.transact(TRANSACTION_requestHotwordDetection, data, null, FLAG_ONEWAY);
} finally {
data.recycle();
}
}
}
}
}

View file

@ -13,7 +13,7 @@ import android.widget.AdapterView;
* based on touch gestures. This class also inherits from
* {@link SimpleFloatViewManager}, which provides basic float View
* creation.
*
* <p>
* An instance of this class is meant to be passed to the methods
* {@link DragSortListView#setTouchListener()} and
* {@link DragSortListView#setFloatViewManager()} of your
@ -27,59 +27,62 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
public static final int ON_DOWN = 0;
public static final int ON_DRAG = 1;
public static final int ON_LONG_PRESS = 2;
private int mDragInitMode = ON_DOWN;
private boolean mSortEnabled = true;
/**
* Remove mode enum.
*/
public static final int CLICK_REMOVE = 0;
public static final int FLING_REMOVE = 1;
public static final int MISS = -1;
private final GestureDetector mDetector;
private final GestureDetector mFlingRemoveDetector;
private final int mTouchSlop;
private final int[] mTempLoc = new int[2];
private final float mFlingSpeed = 500f;
private final DragSortListView mDslv;
protected int mHitPos = MISS;
private int mDragInitMode = ON_DOWN;
private boolean mSortEnabled = true;
/**
* The current remove mode.
*/
private int mRemoveMode;
private boolean mRemoveEnabled = false;
private boolean mIsRemoving = false;
private GestureDetector mDetector;
private GestureDetector mFlingRemoveDetector;
private int mTouchSlop;
public static final int MISS = -1;
protected int mHitPos = MISS;
private int mFlingHitPos = MISS;
private int mClickRemoveHitPos = MISS;
private int[] mTempLoc = new int[2];
private int mItemX;
private int mItemY;
private int mCurrX;
private int mCurrY;
private boolean mDragging = false;
private float mFlingSpeed = 500f;
private int mDragHandleId;
private int mClickRemoveId;
private int mFlingHandleId;
private boolean mCanDrag;
private DragSortListView mDslv;
private int mPositionX;
private final GestureDetector.OnGestureListener mFlingRemoveListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// Log.d("mobeta", "on fling remove called");
if (mRemoveEnabled && mIsRemoving) {
int w = mDslv.getWidth();
int minPos = w / 5;
if (velocityX > mFlingSpeed) {
if (mPositionX > -minPos) {
mDslv.stopDragWithVelocity(true, velocityX);
}
} else if (velocityX < -mFlingSpeed) {
if (mPositionX < minPos) {
mDslv.stopDragWithVelocity(true, velocityX);
}
}
mIsRemoving = false;
}
return false;
}
};
/**
* Calls {@link #DragSortController(DragSortListView, int)} with a
@ -101,15 +104,16 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
this(dslv, dragHandleId, dragInitMode, removeMode, clickRemoveId, 0);
}
/**
* By default, sorting is enabled, and removal is disabled.
*
* @param dslv The DSLV instance
* @param dslv The DSLV instance
* @param dragHandleId The resource id of the View that represents
* the drag handle in a list item.
* the drag handle in a list item.
*/
public DragSortController(DragSortListView dslv, int dragHandleId, int dragInitMode,
int removeMode, int clickRemoveId, int flingHandleId) {
int removeMode, int clickRemoveId, int flingHandleId) {
super(dslv);
mDslv = dslv;
mDetector = new GestureDetector(dslv.getContext(), this);
@ -123,7 +127,6 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
setDragInitMode(dragInitMode);
}
public int getDragInitMode() {
return mDragInitMode;
}
@ -138,19 +141,23 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
mDragInitMode = mode;
}
public boolean isSortEnabled() {
return mSortEnabled;
}
/**
* Enable/Disable list item sorting. Disabling is useful if only item
* removal is desired. Prevents drags in the vertical direction.
*
* @param enabled Set <code>true</code> to enable list
* item sorting.
* item sorting.
*/
public void setSortEnabled(boolean enabled) {
mSortEnabled = enabled;
}
public boolean isSortEnabled() {
return mSortEnabled;
public int getRemoveMode() {
return mRemoveMode;
}
/**
@ -162,8 +169,8 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
mRemoveMode = mode;
}
public int getRemoveMode() {
return mRemoveMode;
public boolean isRemoveEnabled() {
return mRemoveEnabled;
}
/**
@ -173,10 +180,6 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
mRemoveEnabled = enabled;
}
public boolean isRemoveEnabled() {
return mRemoveEnabled;
}
/**
* Set the resource id for the View that represents the drag
* handle in a list item.
@ -213,9 +216,8 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
* Starts the drag on the DragSortListView.
*
* @param position The list item position (includes headers).
* @param deltaX Touch x-coord minus left edge of floating View.
* @param deltaY Touch y-coord minus top edge of floating View.
*
* @param deltaX Touch x-coord minus left edge of floating View.
* @param deltaY Touch y-coord minus top edge of floating View.
* @return True if drag started, false otherwise.
*/
public boolean startDrag(int position, int deltaX, int deltaY) {
@ -295,7 +297,6 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
* event is detected.
*
* @param ev The ACTION_DOWN MotionEvent.
*
* @return The list position to drag if a drag-init gesture is
* detected; MISS if unsuccessful.
*/
@ -313,7 +314,6 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
* if a drag handle touch was detected.
*
* @param ev The ACTION_DOWN MotionEvent.
* @return The list position of the item whose drag handle was
* touched; MISS if unsuccessful.
*/
@ -344,7 +344,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
final int rawX = (int) ev.getRawX();
final int rawY = (int) ev.getRawY();
View dragBox = id == 0 ? item : (View) item.findViewById(id);
View dragBox = id == 0 ? item : item.findViewById(id);
if (dragBox != null) {
dragBox.getLocationOnScreen(mTempLoc);
@ -396,9 +396,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
if (mHitPos != MISS) {
if (mDragInitMode == ON_DRAG && Math.abs(y2 - y1) > mTouchSlop && mSortEnabled) {
startDrag(mHitPos, deltaX, deltaY);
}
else if (mDragInitMode != ON_DOWN && Math.abs(x2 - x1) > mTouchSlop && mRemoveEnabled)
{
} else if (mDragInitMode != ON_DOWN && Math.abs(x2 - x1) > mTouchSlop && mRemoveEnabled) {
mIsRemoving = true;
startDrag(mFlingHitPos, deltaX, deltaY);
}
@ -408,7 +406,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
startDrag(mFlingHitPos, deltaX, deltaY);
} else if (Math.abs(y2 - y1) > mTouchSlop) {
mCanDrag = false; // if started to scroll the list then
// don't allow sorting nor fling-removing
// don't allow sorting nor fling-removing
}
}
}
@ -420,7 +418,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
public void onLongPress(MotionEvent e) {
// Log.d("mobeta", "lift listener long pressed");
if (mHitPos != MISS) {
if(mDragInitMode == ON_LONG_PRESS) {
if (mDragInitMode == ON_LONG_PRESS) {
mDslv.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
startDrag(mHitPos, mCurrX - mItemX, mCurrY - mItemY);
} else {
@ -432,7 +430,7 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
// complete the OnGestureListener interface
@Override
public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(velocityX < 0 && Math.abs(velocityX) > Math.abs(velocityY)) {
if (velocityX < 0 && Math.abs(velocityX) > Math.abs(velocityY)) {
onSwipeLeft();
return true;
}
@ -458,28 +456,4 @@ public class DragSortController extends SimpleFloatViewManager implements View.O
// do nothing
}
private GestureDetector.OnGestureListener mFlingRemoveListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// Log.d("mobeta", "on fling remove called");
if (mRemoveEnabled && mIsRemoving) {
int w = mDslv.getWidth();
int minPos = w / 5;
if (velocityX > mFlingSpeed) {
if (mPositionX > -minPos) {
mDslv.stopDragWithVelocity(true, velocityX);
}
} else if (velocityX < -mFlingSpeed) {
if (mPositionX < minPos) {
mDslv.stopDragWithVelocity(true, velocityX);
}
}
mIsRemoving = false;
}
return false;
}
};
}

View file

@ -14,14 +14,11 @@ import android.widget.ListView;
*/
public class SimpleFloatViewManager implements DragSortListView.FloatViewManager {
private final ListView mListView;
private Bitmap mFloatBitmap;
private ImageView mImageView;
private int mFloatBGColor = Color.BLACK;
private ListView mListView;
public SimpleFloatViewManager(ListView lv) {
mListView = lv;
}

View file

@ -31,40 +31,80 @@ import android.widget.Scroller;
*/
public class AdvancedEditText extends EditText implements OnKeyListener, OnGestureListener {
public interface OnAdvancedEditTextEvent {
public boolean onLeftEdgeSwipe();
public boolean onTap();
public void onPinchStart();
public void onPinchZoom(double scale);
}
/**
* @param context
* the current context
* @param attrs
* some attributes
* @category ObjectLifecycle
*/
public AdvancedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
/**
* The line numbers paint
*/
protected Paint mPaintNumbers;
/**
* The line numbers paint
*/
protected Paint mPaintHighlight;
/**
* the offset value in dp
*/
protected int mPaddingDP = 6;
/**
* the padding scaled
*/
protected int mPadding, mLinePadding;
/**
* the scale for desnity pixels
*/
protected float mScale;
protected float mScaledDensity;
/**
* the scroller instance
*/
protected Scroller mTedScroller;
/**
* the velocity tracker
*/
protected GestureDetector mGestureDetector;
/**
* the Max size of the view
*/
protected Point mMaxSize;
/**
* the highlighted line index
*/
protected int mHighlightedLine;
protected int mHighlightStart;
protected Rect mDrawingRect, mLineBounds;
protected boolean mFlingToScroll = true;
protected boolean mShowLineNumbers;
protected boolean mWordWrap;
protected OnAdvancedEditTextEvent mOnAdvancedEditTextEvent;
private int mDeferredScrollToLine = -1;
private double mInitialPinchDistance;
private int mFirstVisibleLine;
private boolean mSkipNextFling;
mPaintNumbers = new Paint();
mPaintNumbers.setTypeface(Typeface.MONOSPACE);
mPaintNumbers.setAntiAlias(true);
/**
* @param context the current context
* @param attrs some attributes
* @category ObjectLifecycle
*/
public AdvancedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintHighlight = new Paint();
mPaintNumbers = new Paint();
mPaintNumbers.setTypeface(Typeface.MONOSPACE);
mPaintNumbers.setAntiAlias(true);
mPaintHighlight = new Paint();
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
mScale = displayMetrics.density;
mScaledDensity = displayMetrics.scaledDensity;
mScaledDensity = displayMetrics.scaledDensity;
mPadding = (int) (mPaddingDP * mScale);
mPadding = (int) (mPaddingDP * mScale);
mHighlightedLine = mHighlightStart = -1;
mHighlightedLine = mHighlightStart = -1;
mDrawingRect = new Rect();
mLineBounds = new Rect();
mDrawingRect = new Rect();
mLineBounds = new Rect();
mGestureDetector = new GestureDetector(getContext(), this);
mGestureDetector = new GestureDetector(getContext(), this);
mPaintHighlight.setColor(Color.BLACK);
mPaintNumbers.setColor(Color.GRAY);
@ -74,153 +114,152 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
setFlingToScroll(true);
setWordWrap(true);
setShowLineNumbers(true);
}
}
@Override
public void setTextSize(float size) {
super.setTextSize(size);
mPaintNumbers.setTextSize((size>18 ? 18 : size)*mScaledDensity);
updateLinePadding();
mPaintNumbers.setTextSize((size > 18 ? 18 : size) * mScaledDensity);
updateLinePadding();
}
/**
* @see android.widget.TextView#computeScroll()
* @category View
*/
public void computeScroll() {
* @category View
* @see android.widget.TextView#computeScroll()
*/
public void computeScroll() {
if (mTedScroller != null) {
if (mTedScroller.computeScrollOffset()) {
scrollTo(mTedScroller.getCurrX(), mTedScroller.getCurrY());
}
} else {
super.computeScroll();
}
}
if (mTedScroller != null) {
if (mTedScroller.computeScrollOffset()) {
scrollTo(mTedScroller.getCurrX(), mTedScroller.getCurrY());
}
} else {
super.computeScroll();
}
}
private int mDeferredScrollToLine = -1;
public void scrollToLine(int line) {
Layout layout = getLayout();
if(layout == null) {
mDeferredScrollToLine = line;
return;
}
public void scrollToLine(int line) {
Layout layout = getLayout();
if (layout == null) {
mDeferredScrollToLine = line;
return;
}
int count = getLineCount();
Rect r = new Rect();
int count = getLineCount();
Rect r = new Rect();
int line_number = 1;
final String text = getText().toString();
int offset = 0;
for (int i = 0; i < count; i++) {
if(line_number >= line) {
// need to set the selection now, otherwise the EditText will scroll back to the current selection, which is probably not at the same line
setSelection(layout.getLineStart(i));
break;
}
int line_number = 1;
final String text = getText().toString();
int offset = 0;
for (int i = 0; i < count; i++) {
if (line_number >= line) {
// need to set the selection now, otherwise the EditText will scroll back to the current selection, which is probably not at the same line
setSelection(layout.getLineStart(i));
break;
}
getLineBounds(i, r);
offset = r.bottom;
getLineBounds(i, r);
offset = r.bottom;
boolean line_end = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).indexOf('\n')!=-1;
boolean line_end = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).indexOf('\n') != -1;
if(line_end) {
line_number++;
}
}
if (line_end) {
line_number++;
}
}
int max = layout.getLineBounds(count-1, null) - getHeight() - mPadding;
if(max < 0) max = 0;
if(offset > max) {
offset = max;
}
int max = layout.getLineBounds(count - 1, null) - getHeight() - mPadding;
if (max < 0) max = 0;
if (offset > max) {
offset = max;
}
offset -= getHeight()/2;
if(offset < 0) {
offset = 0;
}
offset -= getHeight() / 2;
if (offset < 0) {
offset = 0;
}
scrollTo(0, offset);
}
scrollTo(0, offset);
}
public int getSelectionLine() {
Layout layout = getLayout();
if(layout == null) {
return 1;
}
public int getSelectionLine() {
Layout layout = getLayout();
if (layout == null) {
return 1;
}
int count = getLineCount();
int line_number = 1;
final String text = getText().toString();
int selectionStart = getSelectionStart();
for (int i = 0; i < count; i++) {
if(layout.getLineStart(i) <= selectionStart && layout.getLineEnd(i) > selectionStart) {
return line_number;
}
int count = getLineCount();
int line_number = 1;
final String text = getText().toString();
int selectionStart = getSelectionStart();
for (int i = 0; i < count; i++) {
if (layout.getLineStart(i) <= selectionStart && layout.getLineEnd(i) > selectionStart) {
return line_number;
}
boolean line_end = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).indexOf('\n')!=-1;
boolean line_end = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).indexOf('\n') != -1;
if(line_end) {
line_number++;
}
}
if (line_end) {
line_number++;
}
}
return 1;
}
return 1;
}
/**
* @see android.widget.EditText#onDraw(android.graphics.Canvas)
* @category View
*/
public void onDraw(Canvas canvas) {
/**
* @category View
* @see android.widget.EditText#onDraw(android.graphics.Canvas)
*/
public void onDraw(Canvas canvas) {
final Layout layout = getLayout();
if(layout==null) {
if (layout == null) {
super.onDraw(canvas);
return;
}
if(mDeferredScrollToLine != -1) {
final int l = mDeferredScrollToLine;
mDeferredScrollToLine = -1;
scrollToLine(l);
}
if (mDeferredScrollToLine != -1) {
final int l = mDeferredScrollToLine;
mDeferredScrollToLine = -1;
scrollToLine(l);
}
int count, lineX, baseline;
int count, lineX, baseline;
count = getLineCount();
count = getLineCount();
// get the drawing boundaries
getDrawingRect(mDrawingRect);
// get the drawing boundaries
getDrawingRect(mDrawingRect);
// display current line
computeLineHighlight();
// display current line
computeLineHighlight();
// draw line numbers
lineX = mDrawingRect.left + mLinePadding - mPadding;
int min = 0;
int max = count;
getLineBounds(0, mLineBounds);
int startBottom = mLineBounds.bottom;
int startTop = mLineBounds.top;
getLineBounds(count - 1, mLineBounds);
int endBottom = mLineBounds.bottom;
int endTop = mLineBounds.top;
if (count > 1 && endBottom > startBottom && endTop > startTop) {
min = Math.max(min, ((mDrawingRect.top - startBottom) * (count - 1)) / (endBottom - startBottom));
max = Math.min(max, ((mDrawingRect.bottom - startTop) * (count - 1)) / (endTop - startTop) + 1);
}
// draw line numbers
lineX = mDrawingRect.left + mLinePadding - mPadding;
int min = 0;
int max = count;
getLineBounds(0, mLineBounds);
int startBottom = mLineBounds.bottom;
int startTop = mLineBounds.top;
getLineBounds(count - 1, mLineBounds);
int endBottom = mLineBounds.bottom;
int endTop = mLineBounds.top;
if (count > 1 && endBottom > startBottom && endTop > startTop) {
min = Math.max(min, ((mDrawingRect.top - startBottom) * (count - 1)) / (endBottom - startBottom));
max = Math.min(max, ((mDrawingRect.bottom - startTop) * (count - 1)) / (endTop - startTop) + 1);
}
int line_number = 1;
int first_visible_line = -1;
int first_visible_line = -1;
boolean draw_line_number = true;
final String text = getText().toString();
for (int i = 0; i < max; i++) {
boolean line_end = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).indexOf('\n')!=-1;
if(i >= min) {
for (int i = 0; i < max; i++) {
boolean line_end = text.substring(layout.getLineStart(i), layout.getLineEnd(i)).indexOf('\n') != -1;
if (i >= min) {
baseline = getLineBounds(i, mLineBounds);
if(mLineBounds.top > mDrawingRect.bottom - mPadding) {
// over
break;
}
if (mLineBounds.top > mDrawingRect.bottom - mPadding) {
// over
break;
}
if ((line_number - 1 == mHighlightedLine)) {
canvas.drawRect(mLineBounds, mPaintHighlight);
}
@ -230,62 +269,62 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
}
if (mShowLineNumbers && mLineBounds.bottom >= mDrawingRect.top + mPadding) {
if(first_visible_line == -1) {
first_visible_line = line_number;
mFirstVisibleLine = first_visible_line;
}
if (first_visible_line == -1) {
first_visible_line = line_number;
mFirstVisibleLine = first_visible_line;
}
canvas.drawText(String.valueOf(line_number), mDrawingRect.left + mPadding, baseline, mPaintNumbers);
}
}
}
if(line_end) {
if (line_end) {
line_number++;
}
draw_line_number = line_end;
}
}
if (mShowLineNumbers) {
canvas.drawLine(lineX, mDrawingRect.top, lineX, mDrawingRect.bottom, mPaintNumbers);
}
getLineBounds(count - 1, mLineBounds);
if (mMaxSize != null) {
mMaxSize.y = mLineBounds.bottom;
mMaxSize.x = Math.max(mMaxSize.x + mPadding - mDrawingRect.width(), 0);
getLineBounds(count - 1, mLineBounds);
if (mMaxSize != null) {
mMaxSize.y = mLineBounds.bottom;
mMaxSize.x = Math.max(mMaxSize.x + mPadding - mDrawingRect.width(), 0);
mMaxSize.y = Math.max(mMaxSize.y + mPadding - mDrawingRect.height(), 0);
}
}
super.onDraw(canvas);
}
super.onDraw(canvas);
}
/**
* @see android.view.View.OnKeyListener#onKey(android.view.View, int,
* android.view.KeyEvent)
*/
public boolean onKey(View v, int keyCode, KeyEvent event) {
return false;
}
/**
* @see android.view.View.OnKeyListener#onKey(android.view.View, int,
* android.view.KeyEvent)
*/
public boolean onKey(View v, int keyCode, KeyEvent event) {
return false;
}
/**
* @see android.widget.TextView#onTouchEvent(android.view.MotionEvent)
* @category GestureDetection
*/
public boolean onTouchEvent(MotionEvent event) {
if(mTedScroller != null && !mTedScroller.isFinished()) {
mTedScroller.abortAnimation();
}
/**
* @category GestureDetection
* @see android.widget.TextView#onTouchEvent(android.view.MotionEvent)
*/
public boolean onTouchEvent(MotionEvent event) {
if (mTedScroller != null && !mTedScroller.isFinished()) {
mTedScroller.abortAnimation();
}
if (mGestureDetector != null) {
boolean res = mGestureDetector.onTouchEvent(event);
if(res) {
if (mGestureDetector != null) {
boolean res = mGestureDetector.onTouchEvent(event);
if (res) {
MotionEvent cancel = MotionEvent.obtain(event);
cancel.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(cancel);
return true;
}
}
}
float dx = 0, dy = 0;
boolean two_pointers = event.getPointerCount() == 2;
@ -310,93 +349,93 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
}
return super.onTouchEvent(event);
}
return super.onTouchEvent(event);
}
/**
* @see android.view.GestureDetector.OnGestureListener#onDown(android.view.MotionEvent)
* @category GestureDetection
*/
public boolean onDown(MotionEvent e) {
return false;
}
/**
* @category GestureDetection
* @see android.view.GestureDetector.OnGestureListener#onDown(android.view.MotionEvent)
*/
public boolean onDown(MotionEvent e) {
return false;
}
/**
* @see android.view.GestureDetector.OnGestureListener#onSingleTapUp(android.view.MotionEvent)
* @category GestureDetection
*/
public boolean onSingleTapUp(MotionEvent e) {
/**
* @category GestureDetection
* @see android.view.GestureDetector.OnGestureListener#onSingleTapUp(android.view.MotionEvent)
*/
public boolean onSingleTapUp(MotionEvent e) {
if(mOnAdvancedEditTextEvent != null) {
if (mOnAdvancedEditTextEvent != null) {
boolean res = mOnAdvancedEditTextEvent.onTap();
if(res) {
if (res) {
return true;
}
}
if (isEnabled()) {
((InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE)).showSoftInput(this,
InputMethodManager.SHOW_IMPLICIT);
}
if (isEnabled()) {
((InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE)).showSoftInput(this,
InputMethodManager.SHOW_IMPLICIT);
}
return false;
}
}
/**
* @see android.view.GestureDetector.OnGestureListener#onShowPress(android.view.MotionEvent)
* @category GestureDetection
*/
public void onShowPress(MotionEvent e) {
}
/**
* @category GestureDetection
* @see android.view.GestureDetector.OnGestureListener#onShowPress(android.view.MotionEvent)
*/
public void onShowPress(MotionEvent e) {
}
/**
* @see android.view.GestureDetector.OnGestureListener#onLongPress(android.view.MotionEvent)
*/
public void onLongPress(MotionEvent e) {
/**
* @see android.view.GestureDetector.OnGestureListener#onLongPress(android.view.MotionEvent)
*/
public void onLongPress(MotionEvent e) {
}
}
/**
* @see android.view.GestureDetector.OnGestureListener#onScroll(android.view.MotionEvent,
* android.view.MotionEvent, float, float)
*/
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// mTedScroller.setFriction(0);
if(e1.getX() < mLinePadding && mOnAdvancedEditTextEvent != null) {
mSkipNextFling = true;
/**
* @see android.view.GestureDetector.OnGestureListener#onScroll(android.view.MotionEvent,
* android.view.MotionEvent, float, float)
*/
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// mTedScroller.setFriction(0);
if (e1.getX() < mLinePadding && mOnAdvancedEditTextEvent != null) {
mSkipNextFling = true;
return mOnAdvancedEditTextEvent.onLeftEdgeSwipe();
}
return false;
}
return false;
}
/**
* @see android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent,
* android.view.MotionEvent, float, float)
*/
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (!mFlingToScroll) {
return true;
}
/**
* @see android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent,
* android.view.MotionEvent, float, float)
*/
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (!mFlingToScroll) {
return true;
}
if(mSkipNextFling) {
mSkipNextFling = false;
return true;
}
if (mSkipNextFling) {
mSkipNextFling = false;
return true;
}
if (mTedScroller != null) {
mTedScroller.fling(getScrollX(), getScrollY(), -(int) velocityX,
-(int) velocityY, 0, mMaxSize.x, 0, mMaxSize.y);
}
return true;
}
if (mTedScroller != null) {
mTedScroller.fling(getScrollX(), getScrollY(), -(int) velocityX,
-(int) velocityY, 0, mMaxSize.x, 0, mMaxSize.y);
}
return true;
}
/**
* Update view settings from the app preferences
*
* @category Custom
*/
/**
* Update view settings from the app preferences
*
* @category Custom
*/
/*public void updateFromSettings() {
if (isInEditMode()) {
@ -466,7 +505,6 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
setPadding(mPadding, mPadding, mPadding, mPadding);
}
}*/
public void setFlingToScroll(boolean flingToScroll) {
if (flingToScroll) {
mTedScroller = new Scroller(getContext());
@ -482,17 +520,17 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
updateLinePadding();
}
private void updateLinePadding() {
if (mShowLineNumbers) {
int max_text_size = (int) Math.ceil(mPaintNumbers.measureText("0000"));
mLinePadding = mPadding*3 + max_text_size;
} else {
mLinePadding = mPadding;
}
if(mLinePadding != getPaddingLeft()) {
setPadding(mLinePadding, mPadding, mPadding, mPadding);
}
}
private void updateLinePadding() {
if (mShowLineNumbers) {
int max_text_size = (int) Math.ceil(mPaintNumbers.measureText("0000"));
mLinePadding = mPadding * 3 + max_text_size;
} else {
mLinePadding = mPadding;
}
if (mLinePadding != getPaddingLeft()) {
setPadding(mLinePadding, mPadding, mPadding, mPadding);
}
}
public void setWordWrap(boolean wordWrap) {
mWordWrap = wordWrap;
@ -503,86 +541,60 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
mOnAdvancedEditTextEvent = listener;
}
/**
* Compute the line to highlight based on selection
*/
protected void computeLineHighlight() {
int i, line, selStart;
String text;
/**
* Compute the line to highlight based on selection
*/
protected void computeLineHighlight() {
int i, line, selStart;
String text;
if (!isEnabled()) {
mHighlightedLine = -1;
return;
}
if (!isEnabled()) {
mHighlightedLine = -1;
return;
}
selStart = getSelectionStart();
if (mHighlightStart != selStart) {
text = getText().toString();
selStart = getSelectionStart();
if (mHighlightStart != selStart) {
text = getText().toString();
line = i = 0;
while (i < selStart) {
i = text.indexOf("\n", i);
if (i < 0) {
break;
}
if (i < selStart) {
++line;
}
++i;
}
line = i = 0;
while (i < selStart) {
i = text.indexOf("\n", i);
if (i < 0) {
break;
}
if (i < selStart) {
++line;
}
++i;
}
mHighlightedLine = line;
}
}
/**
* Like {@link EditText#getSelectionStart()} but returns the real start, even with a 'negative' selection.
*/
public int getTrueSelectionStart() {
return Math.min(super.getSelectionStart(), super.getSelectionEnd());
}
/**
* Like {@link EditText#getSelectionEnd()} but returns the real end, even with a 'negative' selection.
*/
public int getTrueSelectionEnd() {
return Math.max(super.getSelectionStart(), super.getSelectionEnd());
}
/** The line numbers paint */
protected Paint mPaintNumbers;
/** The line numbers paint */
protected Paint mPaintHighlight;
/** the offset value in dp */
protected int mPaddingDP = 6;
/** the padding scaled */
protected int mPadding, mLinePadding;
/** the scale for desnity pixels */
protected float mScale;
protected float mScaledDensity;
mHighlightedLine = line;
}
}
/** the scroller instance */
protected Scroller mTedScroller;
/** the velocity tracker */
protected GestureDetector mGestureDetector;
/** the Max size of the view */
protected Point mMaxSize;
/**
* Like {@link EditText#getSelectionStart()} but returns the real start, even with a 'negative' selection.
*/
public int getTrueSelectionStart() {
return Math.min(super.getSelectionStart(), super.getSelectionEnd());
}
/** the highlighted line index */
protected int mHighlightedLine;
protected int mHighlightStart;
/**
* Like {@link EditText#getSelectionEnd()} but returns the real end, even with a 'negative' selection.
*/
public int getTrueSelectionEnd() {
return Math.max(super.getSelectionStart(), super.getSelectionEnd());
}
protected Rect mDrawingRect, mLineBounds;
public interface OnAdvancedEditTextEvent {
boolean onLeftEdgeSwipe();
protected boolean mFlingToScroll = true;
protected boolean mShowLineNumbers;
protected boolean mWordWrap;
boolean onTap();
private double mInitialPinchDistance;
void onPinchStart();
protected OnAdvancedEditTextEvent mOnAdvancedEditTextEvent;
private int mFirstVisibleLine;
private boolean mSkipNextFling;
void onPinchZoom(double scale);
}
}

View file

@ -27,7 +27,6 @@ package net.pierrox.lightning_launcher;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.view.View;
import android.widget.Toast;
@ -103,7 +102,7 @@ public abstract class LLAppPhone extends LLApp {
@Override
public void unlockLockScreen(boolean restore_previous_task) {
if(LockScreen.sThis != null) {
if (LockScreen.sThis != null) {
LockScreen.sThis.unlock(restore_previous_task);
} else {
Toast.makeText(this, net.pierrox.lightning_launcher_extreme.R.string.nly, Toast.LENGTH_SHORT).show();
@ -133,7 +132,7 @@ public abstract class LLAppPhone extends LLApp {
screen.pause();
}
saveAllData();
if(relaunch) {
if (relaunch) {
Intent i = new Intent(this, Dashboard.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
@ -144,10 +143,8 @@ public abstract class LLAppPhone extends LLApp {
@Override
public boolean isLightningIntent(Intent intent) {
ComponentName cn = intent.getComponent();
if(cn != null) {
if(cn.getPackageName().equals(getPackageName()) && cn.getClassName().equals(Dashboard.class.getName())) {
return true;
}
if (cn != null) {
return cn.getPackageName().equals(getPackageName()) && cn.getClassName().equals(Dashboard.class.getName());
}
return false;
}
@ -156,7 +153,7 @@ public abstract class LLAppPhone extends LLApp {
@Override
public void displayPagerPage(int page, boolean reset_navigation_history) {
Screen homeScreen = getScreen(ScreenIdentity.HOME);
if(homeScreen != null) {
if (homeScreen != null) {
homeScreen.loadRootItemLayout(page, reset_navigation_history, true, true);
} else {
mAppEngine.writeCurrentPage(page);

View file

@ -24,40 +24,6 @@ SOFTWARE.
package net.pierrox.lightning_launcher.activities;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.BackupRestoreTool;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.data.PageProcessor;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.data.Widget;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.template.LLTemplateAPI;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONException;
import org.json.JSONObject;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
@ -89,52 +55,49 @@ import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.Toast;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.BackupRestoreTool;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.PageProcessor;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.data.Widget;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher.template.LLTemplateAPI;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class ApplyTemplate extends ResourceWrapperActivity {
/*package*/ static final String INTENT_EXTRA_PATH = "p";
/*package*/ static final String INTENT_EXTRA_URI = "u";
private static final int DIALOG_CONFIRM_APPLY = 1;
private static final int DIALOG_NEED_UPGRADE = 2;
private static final int DIALOG_WARNING = 3;
private static final int REQUEST_BIND_APPWIDGET = 1;
private static final int REQUEST_SELECT_SCREEN_FOR_GOTO = 2;
/*package*/ static final String INTENT_EXTRA_PATH = "p";
/*package*/ static final String INTENT_EXTRA_URI = "u";
private enum ApplyMode {
REPLACE,
MERGE,
UPDATE
}
private ComponentName mTemplateCN;
private String mTemplateDisplayName;
private File mTemplateFile;
private Uri mTemplateUri;
private boolean mBackupFirst;
private ApplyMode mApplyMode = ApplyMode.MERGE;
private boolean mLoadWallpaper;
private int mLLVersionFrom;
private boolean mWarningFreeVersion;
private boolean mWarningScreen;
private boolean mWarningWidget;
private SparseArray<ComponentName> mAppWidgetsToBind;
private ParcelableSparseIntArray mNewAppWidgetIds;
private int mBindWidgetOldId;
private int mBindWidgetNewId;
private int mFromScreenDpi;
private int mFromScreenWidth;
private int mFromScreenHeight;
private int mFromStatusBarHeight;
private File mAppBaseDir;
private ArrayList<Page> mImportedPages;
private static Method sBindAppWidgetIdIfAllowed;
static {
@ -143,24 +106,48 @@ public class ApplyTemplate extends ResourceWrapperActivity {
} catch (NoSuchMethodException e) {
}
}
private ComponentName mTemplateCN;
private String mTemplateDisplayName;
private File mTemplateFile;
private Uri mTemplateUri;
private boolean mBackupFirst;
private ApplyMode mApplyMode = ApplyMode.MERGE;
private boolean mLoadWallpaper;
private int mLLVersionFrom;
private boolean mWarningFreeVersion;
private boolean mWarningScreen;
private boolean mWarningWidget;
private SparseArray<ComponentName> mAppWidgetsToBind;
private ParcelableSparseIntArray mNewAppWidgetIds;
private int mBindWidgetOldId;
private int mBindWidgetNewId;
private int mFromScreenDpi;
private int mFromScreenWidth;
private int mFromScreenHeight;
private int mFromStatusBarHeight;
private File mAppBaseDir;
private ArrayList<Page> mImportedPages;
private ProgressDialog mDialog;
private LinkedList<Pair<Integer, File>> mAppWidgetsToLoad;
@Override
protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME);
super.onCreate(savedInstanceState);
mAppBaseDir = LLApp.get().getAppEngine().getBaseDir();
if(getIntent().hasExtra(INTENT_EXTRA_PATH)) {
if (getIntent().hasExtra(INTENT_EXTRA_PATH)) {
mTemplateFile = new File(getIntent().getStringExtra(INTENT_EXTRA_PATH));
mTemplateDisplayName = mTemplateFile.getName();
} else if(getIntent().hasExtra(INTENT_EXTRA_URI)) {
} else if (getIntent().hasExtra(INTENT_EXTRA_URI)) {
mTemplateUri = getIntent().getParcelableExtra(INTENT_EXTRA_URI);
mTemplateDisplayName = mTemplateUri.getLastPathSegment();
} else {
mTemplateCN = getIntent().getParcelableExtra(LLTemplateAPI.INTENT_TEMPLATE_COMPONENT_NAME);
if(mTemplateCN == null) {
if (mTemplateCN == null) {
finish();
return;
}
@ -169,7 +156,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
Intent filter = new Intent();
filter.setComponent(mTemplateCN);
List<ResolveInfo> ris = pm.queryIntentActivities(filter, 0);
if(ris.size() != 1) {
if (ris.size() != 1) {
finish();
return;
}
@ -177,7 +164,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
mTemplateDisplayName = ris.get(0).activityInfo.loadLabel(pm).toString();
}
if(savedInstanceState != null) {
if (savedInstanceState != null) {
mFromScreenDpi = savedInstanceState.getInt("sd");
mFromScreenWidth = savedInstanceState.getInt("sw");
mFromScreenHeight = savedInstanceState.getInt("sh");
@ -187,25 +174,25 @@ public class ApplyTemplate extends ResourceWrapperActivity {
mWarningFreeVersion = savedInstanceState.getBoolean("wx");
mWarningScreen = savedInstanceState.getBoolean("ws");
mWarningWidget = savedInstanceState.getBoolean("ww");
mAppWidgetsToBind = savedInstanceState.getSparseParcelableArray("wb");
mNewAppWidgetIds = savedInstanceState.getParcelable("nw");
mBindWidgetOldId = savedInstanceState.getInt("oi");
mBindWidgetNewId = savedInstanceState.getInt("ni");
int[] pages_id = savedInstanceState.getIntArray("ip");
if(pages_id != null) {
mImportedPages = new ArrayList<Page>();
LightningEngine engine = LLApp.get().getEngine(getExtractedTemplateDir(), true);
for(int p : pages_id) {
mImportedPages.add(engine.getOrLoadPage(p));
}
if (pages_id != null) {
mImportedPages = new ArrayList<Page>();
LightningEngine engine = LLApp.get().getEngine(getExtractedTemplateDir(), true);
for (int p : pages_id) {
mImportedPages.add(engine.getOrLoadPage(p));
}
}
mApplyMode = ApplyMode.values()[savedInstanceState.getInt("am")];
}
if(checkPermissions(
if (checkPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
new int[] { R.string.pr_r6, R.string.pr_r7},
new int[]{R.string.pr_r6, R.string.pr_r7},
REQUEST_PERMISSION_BASE)) {
showDialog(DIALOG_CONFIRM_APPLY);
}
@ -213,7 +200,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(areAllPermissionsGranted(grantResults, R.string.pr_f4)) {
if (areAllPermissionsGranted(grantResults, R.string.pr_f4)) {
showDialog(DIALOG_CONFIRM_APPLY);
}
}
@ -230,18 +217,18 @@ public class ApplyTemplate extends ResourceWrapperActivity {
outState.putBoolean("wx", mWarningFreeVersion);
outState.putBoolean("ws", mWarningScreen);
outState.putBoolean("ww", mWarningWidget);
outState.putSparseParcelableArray("wb", mAppWidgetsToBind);
outState.putParcelable("nw", mNewAppWidgetIds);
outState.putInt("oi", mBindWidgetOldId);
outState.putInt("ni", mBindWidgetNewId);
if(mImportedPages != null) {
int l = mImportedPages.size();
int[] pages_id = new int[l];
for(int i=0; i<l; i++) {
pages_id[i] = mImportedPages.get(i).id;
}
outState.putIntArray("ip", pages_id);
if (mImportedPages != null) {
int l = mImportedPages.size();
int[] pages_id = new int[l];
for (int i = 0; i < l; i++) {
pages_id[i] = mImportedPages.get(i).id;
}
outState.putIntArray("ip", pages_id);
}
outState.putInt("am", mApplyMode.ordinal());
}
@ -250,15 +237,15 @@ public class ApplyTemplate extends ResourceWrapperActivity {
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder;
switch(id) {
switch (id) {
case DIALOG_CONFIRM_APPLY:
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.apply_tmpl_t);
final View content = getLayoutInflater().inflate(R.layout.dialog_apply_tmpl, null);
final RadioButton rb_replace = (RadioButton) content.findViewById(R.id.tmpl_r);
final RadioButton rb_merge = (RadioButton) content.findViewById(R.id.tmpl_m);
final CheckBox cb_backup = (CheckBox) content.findViewById(R.id.tmpl_b);
final CheckBox cb_wallpaper = (CheckBox) content.findViewById(R.id.tmpl_w);
final RadioButton rb_replace = content.findViewById(R.id.tmpl_r);
final RadioButton rb_merge = content.findViewById(R.id.tmpl_m);
final CheckBox cb_backup = content.findViewById(R.id.tmpl_b);
final CheckBox cb_wallpaper = content.findViewById(R.id.tmpl_w);
rb_replace.setText(R.string.tmpl_r);
rb_merge.setText(R.string.tmpl_m);
@ -269,10 +256,10 @@ public class ApplyTemplate extends ResourceWrapperActivity {
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if(rb_replace.isChecked()) {
mApplyMode = ApplyMode.REPLACE;
} else {
if(rb_merge.isChecked()) {
if (rb_replace.isChecked()) {
mApplyMode = ApplyMode.REPLACE;
} else {
if (rb_merge.isChecked()) {
mApplyMode = ApplyMode.MERGE;
} else {
mApplyMode = ApplyMode.UPDATE;
@ -315,13 +302,13 @@ public class ApplyTemplate extends ResourceWrapperActivity {
builder.setTitle(R.string.tmpl_warn_t);
String msg = getString(R.string.tmpl_warn_m);
if(mWarningFreeVersion) {
if (mWarningFreeVersion) {
msg += "\n\n" + getString(R.string.tmpl_warn_llx);
}
if(mWarningScreen) {
if (mWarningScreen) {
msg += "\n\n" + getString(R.string.tmpl_warn_screen);
}
if(mWarningWidget) {
if (mWarningWidget) {
msg += "\n\n" + getString(R.string.tmpl_warn_widget);
}
builder.setMessage(msg);
@ -331,7 +318,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
applyTemplate();
}
});
if(mWarningFreeVersion) {
if (mWarningFreeVersion) {
builder.setNeutralButton(R.string.tmpl_get_llx, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
@ -368,9 +355,12 @@ public class ApplyTemplate extends ResourceWrapperActivity {
protected JSONObject doInBackground(Void... voids) {
InputStream is = openTemplateStream();
if(is != null) {
if (is != null) {
JSONObject manifest = BackupRestoreTool.readManifest(is);
try { is.close(); } catch(IOException e) {}
try {
is.close();
} catch (IOException e) {
}
return manifest;
} else {
return null;
@ -380,13 +370,13 @@ public class ApplyTemplate extends ResourceWrapperActivity {
@Override
protected void onPostExecute(JSONObject manifest) {
mDialog.dismiss();
if(manifest == null) {
if (manifest == null) {
Toast.makeText(ApplyTemplate.this, R.string.tmpl_check_e, Toast.LENGTH_SHORT).show();
finish();
} else {
try {
mLLVersionFrom = Utils.getVersionCode(manifest.getInt(BackupRestoreTool.MANIFEST_LL_VERSION));
if(mLLVersionFrom > Utils.getMyPackageVersion(ApplyTemplate.this)) {
if (mLLVersionFrom > Utils.getMyPackageVersion(ApplyTemplate.this)) {
showDialog(DIALOG_NEED_UPGRADE);
return;
}
@ -399,11 +389,11 @@ public class ApplyTemplate extends ResourceWrapperActivity {
mFromScreenHeight = manifest.getInt(BackupRestoreTool.MANIFEST_SCREEN_HEIGHT);
mFromStatusBarHeight = manifest.getInt(BackupRestoreTool.MANIFEST_SB_HEIGHT);
int screenDensity = manifest.getInt(BackupRestoreTool.MANIFEST_SCREEN_DENSITY);
mWarningScreen = (mFromScreenWidth!=dm.widthPixels || mFromScreenHeight!=dm.heightPixels || screenDensity!=dm.densityDpi);
mWarningScreen = (mFromScreenWidth != dm.widthPixels || mFromScreenHeight != dm.heightPixels || screenDensity != dm.densityDpi);
mWarningWidget = sBindAppWidgetIdIfAllowed==null;
mWarningWidget = sBindAppWidgetIdIfAllowed == null;
if(mWarningFreeVersion || mWarningScreen || mWarningWidget) {
if (mWarningFreeVersion || mWarningScreen || mWarningWidget) {
showDialog(DIALOG_WARNING);
} else {
applyTemplate();
@ -413,34 +403,32 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
}
}
}.execute((Void)null);
}.execute((Void) null);
}
private ProgressDialog mDialog;
private File getExtractedTemplateDir() {
String tempTemplatePath = FileUtils.LL_TMP_DIR+"/template";
String tempTemplatePath = FileUtils.LL_TMP_DIR + "/template";
return new File(tempTemplatePath);
}
private void applyTemplate() {
new AsyncTask<Void, Boolean, Integer>() {
private File mTemplateDir;
private LightningEngine mEngineFrom;
private LightningEngine mEngineTo;
private SparseIntArray mTranslatedPageIds;
private SparseIntArray mTranslatedScriptIds;
private File mTemplateDir;
private LightningEngine mEngineFrom;
private LightningEngine mEngineTo;
private SparseIntArray mTranslatedPageIds;
private SparseIntArray mTranslatedScriptIds;
@Override
protected void onPreExecute() {
mTemplateDir = getExtractedTemplateDir();
mEngineFrom = LLApp.get().getEngine(mTemplateDir, false);
mEngineTo = LLApp.get().getAppEngine();
mImportedPages = new ArrayList<>();
mTranslatedPageIds = null;
mTranslatedScriptIds = null;
mTemplateDir = getExtractedTemplateDir();
mEngineFrom = LLApp.get().getEngine(mTemplateDir, false);
mEngineTo = LLApp.get().getAppEngine();
mImportedPages = new ArrayList<>();
mTranslatedPageIds = null;
mTranslatedScriptIds = null;
mDialog = new ProgressDialog(ApplyTemplate.this);
mDialog.setMessage(getString(mBackupFirst ? R.string.backup_in_progress : R.string.apply_tmpl_g));
mDialog.setCancelable(false);
@ -450,23 +438,23 @@ public class ApplyTemplate extends ResourceWrapperActivity {
@Override
protected Integer doInBackground(Void... voids) {
Context context = ApplyTemplate.this;
if(mBackupFirst) {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH-mm");
String backup_name=sdf.format(new Date());
String backup_path= FileUtils.LL_EXT_DIR +"/"+getString(R.string.backup_d)+"-"+backup_name;
if (mBackupFirst) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm");
String backup_name = sdf.format(new Date());
String backup_path = FileUtils.LL_EXT_DIR + "/" + getString(R.string.backup_d) + "-" + backup_name;
BackupRestoreTool.BackupConfig backup_config=new BackupRestoreTool.BackupConfig();
BackupRestoreTool.BackupConfig backup_config = new BackupRestoreTool.BackupConfig();
backup_config.context=context;
backup_config.pathFrom=mAppBaseDir.getAbsolutePath();
backup_config.pathTo=backup_path;
backup_config.includeWidgetsData=true;
backup_config.includeWallpaper=true;
backup_config.includeFonts=true;
backup_config.context = context;
backup_config.pathFrom = mAppBaseDir.getAbsolutePath();
backup_config.pathTo = backup_path;
backup_config.includeWidgetsData = true;
backup_config.includeWallpaper = true;
backup_config.includeFonts = true;
Exception exception = BackupRestoreTool.backup(backup_config);
if(exception != null) {
if (exception != null) {
exception.printStackTrace();
return 1;
}
@ -474,28 +462,28 @@ public class ApplyTemplate extends ResourceWrapperActivity {
publishProgress(true);
}
BackupRestoreTool.RestoreConfig restore_config=new BackupRestoreTool.RestoreConfig();
BackupRestoreTool.RestoreConfig restore_config = new BackupRestoreTool.RestoreConfig();
restore_config.context=context;
restore_config.pathTo=mApplyMode==ApplyMode.REPLACE ? mAppBaseDir.getAbsolutePath() : mTemplateDir.getAbsolutePath();
restore_config.context = context;
restore_config.pathTo = mApplyMode == ApplyMode.REPLACE ? mAppBaseDir.getAbsolutePath() : mTemplateDir.getAbsolutePath();
restore_config.isFrom = openTemplateStream();
restore_config.restoreWidgetsData=true;
restore_config.restoreWallpaper=mLoadWallpaper;
restore_config.restoreFonts=true;
restore_config.restoreWidgetsData = true;
restore_config.restoreWallpaper = mLoadWallpaper;
restore_config.restoreFonts = true;
if(!BackupRestoreTool.restore(restore_config)) {
Utils.deleteDirectory(mTemplateDir, true);
if (!BackupRestoreTool.restore(restore_config)) {
Utils.deleteDirectory(mTemplateDir, true);
return 2;
}
mEngineFrom.init();
if(mApplyMode == ApplyMode.MERGE) {
if (mApplyMode == ApplyMode.MERGE) {
// build the list of desktops to import recursively
ArrayList<Page> desktopPages = new ArrayList<Page>();
for (int p : mEngineFrom.getPageManager().getAllPagesIds()) {
if(Page.isDashboard(p) && p != Page.APP_DRAWER_PAGE) {
if (Page.isDashboard(p) && p != Page.APP_DRAWER_PAGE) {
// skip folders and the app drawer pages when merging
desktopPages.add(mEngineFrom.getOrLoadPage(p));
}
@ -503,31 +491,31 @@ public class ApplyTemplate extends ResourceWrapperActivity {
// do the grunt work of importing
mTranslatedPageIds = mEngineTo.getPageManager().clonePages(desktopPages, true);
for(int i=0; i<mTranslatedPageIds.size(); i++) {
for (int i = 0; i < mTranslatedPageIds.size(); i++) {
mImportedPages.add(mEngineTo.getOrLoadPage(mTranslatedPageIds.valueAt(i)));
}
// update the list of desktops in the global config of the target engine
GlobalConfig template_gc = mEngineFrom.getGlobalConfig();
GlobalConfig app_gc = mEngineTo.getGlobalConfig();
int l = app_gc.screensOrder.length;
int n = l+desktopPages.size();
int[] new_screens_order = new int[n];
String[] new_screens_names = new String[n];
System.arraycopy(app_gc.screensOrder, 0, new_screens_order, 0, l);
System.arraycopy(app_gc.screensNames, 0, new_screens_names, 0, l);
int i=l;
for(Page page : desktopPages) {
int old_page_id = page.id;
// update the list of desktops in the global config of the target engine
GlobalConfig template_gc = mEngineFrom.getGlobalConfig();
GlobalConfig app_gc = mEngineTo.getGlobalConfig();
int l = app_gc.screensOrder.length;
int n = l + desktopPages.size();
int[] new_screens_order = new int[n];
String[] new_screens_names = new String[n];
System.arraycopy(app_gc.screensOrder, 0, new_screens_order, 0, l);
System.arraycopy(app_gc.screensNames, 0, new_screens_names, 0, l);
int i = l;
for (Page page : desktopPages) {
int old_page_id = page.id;
new_screens_names[i] = template_gc.screensNames[template_gc.getPageIndex(old_page_id)];
new_screens_order[i] = mTranslatedPageIds.get(old_page_id);
i++;
}
app_gc.screensNames = new_screens_names;
app_gc.screensOrder = new_screens_order;
mEngineTo.notifyGlobalConfigChanged();
}
app_gc.screensNames = new_screens_names;
app_gc.screensOrder = new_screens_order;
mEngineTo.notifyGlobalConfigChanged();
// copy font files
File[] fonts = FileUtils.getFontsDir(mEngineFrom.getBaseDir()).listFiles();
@ -541,50 +529,50 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
// translate scripts
ScriptManager scriptManagerTo = mEngineTo.getScriptManager();
ArrayList<Script> my_scripts = scriptManagerTo.getAllScriptMatching(Script.FLAG_ALL);
mTranslatedScriptIds = new SparseIntArray();
mTranslatedScriptIds = new SparseIntArray();
ScriptManager scriptManagerFrom = mEngineFrom.getScriptManager();
ArrayList<Script> scriptsToImport = scriptManagerFrom.getAllScriptMatching(Script.FLAG_ALL);
String relativePath;
if(mTemplateFile != null) {
if (mTemplateFile != null) {
relativePath = mTemplateFile.getName();
} else if(mTemplateUri != null) {
} else if (mTemplateUri != null) {
relativePath = mTemplateUri.getLastPathSegment();
} else if(mTemplateCN != null) {
} else if (mTemplateCN != null) {
relativePath = "/" + mTemplateCN.getPackageName().replace('.', '/');
} else {
relativePath = "/";
}
for(Script script : scriptsToImport) {
Script matching_script = null;
for(Script my_script : my_scripts) {
if(my_script.name.equals(script.name) && my_script.getSourceText().equals(script.getSourceText())) {
matching_script = my_script;
break;
}
}
int old_id = script.id;
int new_id;
if(matching_script != null) {
// reuse existing identical script
new_id = matching_script.id;
} else {
// copy script
for (Script script : scriptsToImport) {
Script matching_script = null;
for (Script my_script : my_scripts) {
if (my_script.name.equals(script.name) && my_script.getSourceText().equals(script.getSourceText())) {
matching_script = my_script;
break;
}
}
int old_id = script.id;
int new_id;
if (matching_script != null) {
// reuse existing identical script
new_id = matching_script.id;
} else {
// copy script
Script importedScript = scriptManagerTo.importScript(script);
if(importedScript.getRelativePath().equals("/")) {
if (importedScript.getRelativePath().equals("/")) {
importedScript.setRelativePath(relativePath);
}
new_id = importedScript.id;
}
mTranslatedScriptIds.put(old_id, new_id);
}
}
Utils.deleteDirectory(mTemplateDir, true);
} else if(mApplyMode == ApplyMode.REPLACE) {
mTranslatedScriptIds.put(old_id, new_id);
}
Utils.deleteDirectory(mTemplateDir, true);
} else if (mApplyMode == ApplyMode.REPLACE) {
for (int p : mEngineTo.getPageManager().getAllPagesIds()) {
mImportedPages.add(mEngineTo.getOrLoadPage(p));
}
@ -592,19 +580,19 @@ public class ApplyTemplate extends ResourceWrapperActivity {
// build list of widgets to bind
mAppWidgetsToBind = new SparseArray<>();
for(Page page : mImportedPages) {
for(Item i : page.items) {
if(i.getClass() == Widget.class) {
Widget w = (Widget)i;
for (Page page : mImportedPages) {
for (Item i : page.items) {
if (i.getClass() == Widget.class) {
Widget w = (Widget) i;
ComponentName cn = w.getComponentName();
int id = w.getAppWidgetId();
if(cn != null && id != Widget.NO_APP_WIDGET_ID) {
if (cn != null && id != Widget.NO_APP_WIDGET_ID) {
mAppWidgetsToBind.put(id, cn);
}
}
}
}
}
// replace package name and scale positions
Resources resources = getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
@ -623,33 +611,33 @@ public class ApplyTemplate extends ResourceWrapperActivity {
// reload app drawer and clear state file
// boolean is_llx = getPackageName().equals(LLApp.LLX_PKG_NAME);
// if(!is_llx) {
if(mApplyMode == ApplyMode.REPLACE) {
Page app_drawer = LLApp.get().getAppEngine().getOrLoadPage(Page.APP_DRAWER_PAGE);
app_drawer.items=Utils.loadAppDrawerShortcuts(app_drawer);
if (mApplyMode == ApplyMode.REPLACE) {
Page app_drawer = LLApp.get().getAppEngine().getOrLoadPage(Page.APP_DRAWER_PAGE);
app_drawer.items = Utils.loadAppDrawerShortcuts(app_drawer);
Utils.layoutItemsInTable(app_drawer.config, app_drawer.items, true);
app_drawer.setModified();
app_drawer.save();
app_drawer.setModified();
app_drawer.save();
FileUtils.getStateFile(mAppBaseDir).delete();
mEngineTo.reloadGlobalConfig();
} else {
} else {
mEngineTo.saveData();
}
return 0;
}
@Override
@Override
protected void onPostExecute(Integer result) {
switch(result) {
switch (result) {
case 0:
if(sBindAppWidgetIdIfAllowed != null) {
if(mApplyMode == ApplyMode.REPLACE) {
AppWidgetHost h = LLApp.get().getAppWidgetHost();
h.deleteHost();
h.startListening();
}
if (sBindAppWidgetIdIfAllowed != null) {
if (mApplyMode == ApplyMode.REPLACE) {
AppWidgetHost h = LLApp.get().getAppWidgetHost();
h.deleteHost();
h.startListening();
}
mNewAppWidgetIds = new ParcelableSparseIntArray();
bindNextAppWidget();
} else {
@ -660,7 +648,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
default:
mDialog.dismiss();
Toast.makeText(ApplyTemplate.this, result==1 ? R.string.backup_error : R.string.apply_tmpl_e, Toast.LENGTH_SHORT).show();
Toast.makeText(ApplyTemplate.this, result == 1 ? R.string.backup_error : R.string.apply_tmpl_e, Toast.LENGTH_SHORT).show();
finish();
break;
}
@ -674,7 +662,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
private InputStream openTemplateStream() {
if(mTemplateFile != null) {
if (mTemplateFile != null) {
try {
return new FileInputStream(mTemplateFile);
} catch (IOException e) {
@ -682,7 +670,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
return null;
}
} else if(mTemplateUri != null) {
} else if (mTemplateUri != null) {
try {
return getContentResolver().openInputStream(mTemplateUri);
} catch (IOException e) {
@ -700,16 +688,16 @@ public class ApplyTemplate extends ResourceWrapperActivity {
try {
return template_context.getAssets(). open("lightning_launcher/"+mTemplateCN.getClassName());
return template_context.getAssets().open("lightning_launcher/" + mTemplateCN.getClassName());
} catch (IOException e) {
e.printStackTrace();
try {
String simple_name = mTemplateCN.getShortClassName().toLowerCase();
if(simple_name.charAt(0) == '.') simple_name = simple_name.substring(1);
if (simple_name.charAt(0) == '.') simple_name = simple_name.substring(1);
int id = template_context.getResources().getIdentifier(simple_name, "raw", mTemplateCN.getPackageName());
return template_context.getResources().openRawResource(id);
} catch(Resources.NotFoundException e1) {
} catch (Resources.NotFoundException e1) {
e.printStackTrace();
return null;
}
@ -718,7 +706,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
private void bindNextAppWidget() {
if(sBindAppWidgetIdIfAllowed == null || mAppWidgetsToBind.size() == 0) {
if (sBindAppWidgetIdIfAllowed == null || mAppWidgetsToBind.size() == 0) {
updateAppWidgetIds();
} else {
int old_id = mAppWidgetsToBind.keyAt(0);
@ -726,11 +714,11 @@ public class ApplyTemplate extends ResourceWrapperActivity {
ComponentName cn = mAppWidgetsToBind.valueAt(0);
boolean ok;
try {
ok = (Boolean)sBindAppWidgetIdIfAllowed.invoke(AppWidgetManager.getInstance(this), new_id, cn);
ok = (Boolean) sBindAppWidgetIdIfAllowed.invoke(AppWidgetManager.getInstance(this), new_id, cn);
} catch (Exception e) {
ok = false;
}
if(ok) {
if (ok) {
mNewAppWidgetIds.put(old_id, new_id);
mAppWidgetsToBind.remove(old_id);
bindNextAppWidget();
@ -745,25 +733,23 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
}
private LinkedList<Pair<Integer,File>> mAppWidgetsToLoad;
private void updateAppWidgetIds() {
mAppWidgetsToLoad = new LinkedList<Pair<Integer,File>>();
mAppWidgetsToLoad = new LinkedList<Pair<Integer, File>>();
AppWidgetManager awm = AppWidgetManager.getInstance(this);
for(Page page : mImportedPages) {
for (Page page : mImportedPages) {
boolean modified = false;
for(Item i : page.items) {
if(i.getClass() == Widget.class) {
Widget w = (Widget)i;
for (Item i : page.items) {
if (i.getClass() == Widget.class) {
Widget w = (Widget) i;
int old_id = w.getAppWidgetId();
int new_id = mNewAppWidgetIds.get(old_id);
if(new_id != 0) {
if (new_id != 0) {
w.setAppWidgetId(new_id);
AppWidgetProviderInfo appWidgetInfo = awm.getAppWidgetInfo(new_id);
// don't know why but sometimes appWidgetInfo can be null
if(appWidgetInfo != null) {
if (appWidgetInfo != null) {
w.setAppWidgetLabel(appWidgetInfo.label);
File tmp_widget_file = new File(FileUtils.LL_TMP_DIR, String.valueOf(old_id));
@ -789,7 +775,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
double from_screen_phys_width = (double) mFromScreenWidth / mFromScreenDpi;
double to_screen_phys_width = (double) dm.widthPixels / dm.densityDpi;
File patched_widget_file = new File(FileUtils.LL_TMP_DIR, String.valueOf(old_id) + "p");
File patched_widget_file = new File(FileUtils.LL_TMP_DIR, old_id + "p");
FileInputStream fis = null;
FileOutputStream fos = null;
ZipInputStream zis = null;
@ -850,7 +836,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
// json.put("preset_dpiheight", (int)(json.getDouble("preset_dpiheight") * ratio_height / ratio_dpi));
// json.put("pref_widget_scale", widget_scale * (widget_width>widget_height ? ratio_width : ratio_height));
zos.write(json.toString().getBytes("utf-8"));
zos.write(json.toString().getBytes(StandardCharsets.UTF_8));
} else {
while ((n = zis.read(buffer, 0, buffer.length)) > 0) {
zos.write(buffer, 0, n);
@ -898,7 +884,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
}
if(modified) {
if (modified) {
page.setModified();
page.save();
}
@ -909,8 +895,8 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
private void loadNextWidgetOrStop() {
if(mAppWidgetsToLoad.size() == 0) {
if(mApplyMode == ApplyMode.MERGE) {
if (mAppWidgetsToLoad.size() == 0) {
if (mApplyMode == ApplyMode.MERGE) {
selectDesktopToGoTo();
} else {
restart();
@ -928,8 +914,8 @@ public class ApplyTemplate extends ResourceWrapperActivity {
final File widget_file = item.second;
AppWidgetManager awm = AppWidgetManager.getInstance(this);
AppWidgetProviderInfo app_widget_info=awm.getAppWidgetInfo(new_id);
if(app_widget_info == null) {
AppWidgetProviderInfo app_widget_info = awm.getAppWidgetInfo(new_id);
if (app_widget_info == null) {
loadNextWidgetOrStop();
} else {
Uri tmp_widget_uri = Uri.fromFile(widget_file);
@ -953,14 +939,14 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
}
}
private void selectDesktopToGoTo() {
LLApp.get().getAppEngine().getPageManager().clear();
Intent intent = new Intent(this, ScreenManager.class);
LLApp.get().getAppEngine().getPageManager().clear();
Intent intent = new Intent(this, ScreenManager.class);
intent.setAction(Intent.ACTION_PICK);
startActivityForResult(intent, REQUEST_SELECT_SCREEN_FOR_GOTO);
}
private void restart() {
Utils.deleteDirectory(FileUtils.LL_TMP_DIR, false);
startActivity(new Intent(this, Dashboard.class));
@ -969,24 +955,30 @@ public class ApplyTemplate extends ResourceWrapperActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_BIND_APPWIDGET) {
if(resultCode == RESULT_OK) {
if (requestCode == REQUEST_BIND_APPWIDGET) {
if (resultCode == RESULT_OK) {
mNewAppWidgetIds.put(mBindWidgetOldId, mBindWidgetNewId);
} else {
LLApp.get().getAppWidgetHost().deleteAppWidgetId(mBindWidgetNewId);
}
mAppWidgetsToBind.remove(mBindWidgetOldId);
bindNextAppWidget();
} else if(requestCode == REQUEST_SELECT_SCREEN_FOR_GOTO) {
if(resultCode == RESULT_OK) {
LLApp.get().getAppEngine().writeCurrentPage(data.getIntExtra(API.SCREEN_PICKER_INTENT_EXTRA_SCREEN, Page.FIRST_DASHBOARD_PAGE));
}
} else if (requestCode == REQUEST_SELECT_SCREEN_FOR_GOTO) {
if (resultCode == RESULT_OK) {
LLApp.get().getAppEngine().writeCurrentPage(data.getIntExtra(API.SCREEN_PICKER_INTENT_EXTRA_SCREEN, Page.FIRST_DASHBOARD_PAGE));
}
restart();
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private enum ApplyMode {
REPLACE,
MERGE,
UPDATE
}
private static class ParcelableSparseIntArray implements Cloneable, Parcelable {
public static final Creator<ParcelableSparseIntArray> CREATOR = new Creator<ParcelableSparseIntArray>() {
@Override
@ -1004,6 +996,19 @@ public class ApplyTemplate extends ResourceWrapperActivity {
return new ParcelableSparseIntArray[size];
}
};
private int[] mKeys;
private int mSize;
private int[] mValues;
public ParcelableSparseIntArray() {
this(10);
}
public ParcelableSparseIntArray(int initialCapacity) {
mKeys = new int[initialCapacity];
mValues = new int[initialCapacity];
mSize = 0;
}
private static int binarySearch(int[] a, int start, int len, int key) {
int high = start + len, low = start - 1, guess;
@ -1024,22 +1029,6 @@ public class ApplyTemplate extends ResourceWrapperActivity {
}
}
private int[] mKeys;
private int mSize;
private int[] mValues;
public ParcelableSparseIntArray() {
this(10);
}
public ParcelableSparseIntArray(int initialCapacity) {
mKeys = new int[initialCapacity];
mValues = new int[initialCapacity];
mSize = 0;
}
// public ParcelableSparseIntArray(ParcelableSparseIntArray arrayForCopy) {
// if (arrayForCopy == null) {
// int initialCapacity = arrayForCopy.mSize;
@ -1078,7 +1067,7 @@ public class ApplyTemplate extends ResourceWrapperActivity {
@Override
public ParcelableSparseIntArray clone() {
ParcelableSparseIntArray clone = null;
ParcelableSparseIntArray clone = null;
try {
clone = (ParcelableSparseIntArray) super.clone();
clone.mKeys = mKeys.clone();

View file

@ -24,33 +24,6 @@ SOFTWARE.
package net.pierrox.lightning_launcher.activities;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.data.BackupRestoreTool;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Folder;
import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.util.FileProvider;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONObject;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
@ -79,14 +52,41 @@ import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.data.BackupRestoreTool;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Folder;
import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.util.FileProvider;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONObject;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
public class BackupRestore extends ResourceWrapperActivity implements View.OnClickListener, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, OnLongClickListener {
private static final int DIALOG_BACKUP_IN_PROGRESS=1;
private static final int DIALOG_RESTORE_IN_PROGRESS=2;
private static final int DIALOG_SELECT_ARCHIVE_NAME=3;
private static final int DIALOG_SELECT_BACKUP_ACTION=4;
private static final int DIALOG_CONFIRM_RESTORE=5;
private static final int DIALOG_CONFIRM_DELETE=6;
private static final int DIALOG_BACKUP_IN_PROGRESS = 1;
private static final int DIALOG_RESTORE_IN_PROGRESS = 2;
private static final int DIALOG_SELECT_ARCHIVE_NAME = 3;
private static final int DIALOG_SELECT_BACKUP_ACTION = 4;
private static final int DIALOG_CONFIRM_RESTORE = 5;
private static final int DIALOG_CONFIRM_DELETE = 6;
private static final int REQUEST_SELECT_PAGES_FOR_EXPORT = 1;
private static final int REQUEST_SELECT_FILE_TO_IMPORT = 2;
private static final int REQUEST_SELECT_FILE_TO_LOAD = 3;
@ -97,51 +97,51 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
private boolean mSelectArchiveNameForBackup;
private String mArchiveName;
private Uri mArchiveUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME);
super.onCreate(savedInstanceState);
setContentView(R.layout.backup_restore);
Button backup = (Button) findViewById(R.id.backup);
Button backup = findViewById(R.id.backup);
backup.setText(R.string.backup_t);
backup.setOnClickListener(this);
Button import_ = (Button) findViewById(R.id.import_);
Button import_ = findViewById(R.id.import_);
import_.setText(R.string.import_t);
import_.setOnClickListener(this);
import_.setOnLongClickListener(this);
Button export = (Button) findViewById(R.id.export);
Button export = findViewById(R.id.export);
export.setText(R.string.tmpl_e_t);
export.setOnClickListener(this);
export.setOnLongClickListener(this);
mListView = (ListView) findViewById(R.id.archives);
mListView = findViewById(R.id.archives);
mListView.setOnItemClickListener(this);
mListView.setOnItemLongClickListener(this);
mEmptyView = (TextView) findViewById(R.id.empty);
mEmptyView = findViewById(R.id.empty);
mEmptyView.setText(R.string.no_backup_archive);
loadArchivesList();
if(LLApp.get().isTrialVersion()) {
if (LLApp.get().isTrialVersion()) {
Toast.makeText(this, R.string.tr_fl_t, Toast.LENGTH_SHORT).show();
} else {
checkPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
new int[] { R.string.pr_r1, R.string.pr_r2},
new int[]{R.string.pr_r1, R.string.pr_r2},
REQUEST_PERMISSION_BASE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(areAllPermissionsGranted(grantResults, R.string.pr_f1)) {
if (areAllPermissionsGranted(grantResults, R.string.pr_f1)) {
loadArchivesList();
}
}
@ -151,7 +151,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
super.onResume();
Intent intent = getIntent();
if(Intent.ACTION_VIEW.equals(intent.getAction())) {
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
intent.setAction(Intent.ACTION_MAIN);
loadArchive(intent.getData(), null);
}
@ -164,7 +164,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
return !file.isDirectory();
}
});
if(archives==null || archives.length==0) {
if (archives == null || archives.length == 0) {
mEmptyView.setVisibility(View.VISIBLE);
mListView.setVisibility(View.GONE);
} else {
@ -173,13 +173,13 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
public int compare(File file1, File file2) {
long a = file1.lastModified();
long b = file2.lastModified();
if(a<b) return 1;
if(a>b) return -1;
if (a < b) return 1;
if (a > b) return -1;
return 0;
}
});
String[] archives_names = new String[archives.length];
for(int i=0; i<archives.length; i++) {
for (int i = 0; i < archives.length; i++) {
archives_names[i] = archives[i].getName();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, archives_names);
@ -205,10 +205,10 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
break;
}
}
@Override
public boolean onLongClick(View view) {
switch(view.getId()) {
@Override
public boolean onLongClick(View view) {
switch (view.getId()) {
case R.id.export:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.pierrox.net/cmsms/applications/lightning-launcher/templates.html")));
return true;
@ -217,15 +217,15 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
selectFileToLoadOrImport(false);
return true;
}
return false;
}
return false;
}
@Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder;
ProgressDialog progress;
switch(id) {
switch (id) {
case DIALOG_BACKUP_IN_PROGRESS:
progress = new ProgressDialog(this);
progress.setMessage(getString(R.string.backup_in_progress));
@ -242,9 +242,9 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_n);
final String archive_name;
if(mArchiveName == null) {
if (mArchiveName == null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm");
archive_name = getString(mSelectArchiveNameForBackup ? R.string.backup_d : R.string.tmpl_fn)+"-"+sdf.format(new Date())+".lla";
archive_name = getString(mSelectArchiveNameForBackup ? R.string.backup_d : R.string.tmpl_fn) + "-" + sdf.format(new Date()) + ".lla";
} else {
archive_name = mArchiveName;
}
@ -259,18 +259,18 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String name = edit_text.getText().toString().trim();
String archive_path= FileUtils.LL_EXT_DIR +"/"+name;
File old_archive_file = mArchiveName==null ? null : new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName);
if(old_archive_file!=null && old_archive_file.exists()) {
String archive_path = FileUtils.LL_EXT_DIR + "/" + name;
File old_archive_file = mArchiveName == null ? null : new File(FileUtils.LL_EXT_DIR + "/" + mArchiveName);
if (old_archive_file != null && old_archive_file.exists()) {
old_archive_file.renameTo(new File(archive_path));
loadArchivesList();
} else {
if(mSelectArchiveNameForBackup) {
new BackupTask().execute(archive_path);
} else {
mArchiveName = FileUtils.LL_EXT_DIR +"/"+name;
selectDesktopsToExport();
}
if (mSelectArchiveNameForBackup) {
new BackupTask().execute(archive_path);
} else {
mArchiveName = FileUtils.LL_EXT_DIR + "/" + name;
selectDesktopsToExport();
}
}
}
});
@ -278,14 +278,14 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
return builder.create();
case DIALOG_CONFIRM_RESTORE:
if(mArchiveName != null || mArchiveUri != null) {
if (mArchiveName != null || mArchiveUri != null) {
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_rc);
builder.setMessage(mArchiveName==null ? getNameForUri(mArchiveUri) : mArchiveName);
builder.setMessage(mArchiveName == null ? getNameForUri(mArchiveUri) : mArchiveName);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if(mArchiveName == null) {
if (mArchiveName == null) {
new RestoreTask(mArchiveUri).execute();
} else {
String path;
@ -304,14 +304,14 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
break;
case DIALOG_CONFIRM_DELETE:
if(mArchiveName != null) {
if (mArchiveName != null) {
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_dc);
builder.setMessage(mArchiveName);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName).delete();
new File(FileUtils.LL_EXT_DIR + "/" + mArchiveName).delete();
loadArchivesList();
}
});
@ -321,37 +321,43 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
break;
case DIALOG_SELECT_BACKUP_ACTION:
if(mArchiveName != null) {
if (mArchiveName != null) {
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_a);
builder.setItems(new String[] { getString(R.string.br_ob), getString(R.string.br_ot), getString(R.string.br_r), getString(R.string.br_s), getString(R.string.br_d)}, new DialogInterface.OnClickListener() {
builder.setItems(new String[]{getString(R.string.br_ob), getString(R.string.br_ot), getString(R.string.br_r), getString(R.string.br_s), getString(R.string.br_d)}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
switch(i) {
case 0:
new BackupTask().execute(FileUtils.LL_EXT_DIR +"/"+mArchiveName);
break;
case 1:
mArchiveName = FileUtils.LL_EXT_DIR +"/"+mArchiveName;
selectDesktopsToExport();
break;
switch (i) {
case 0:
new BackupTask().execute(FileUtils.LL_EXT_DIR + "/" + mArchiveName);
break;
case 1:
mArchiveName = FileUtils.LL_EXT_DIR + "/" + mArchiveName;
selectDesktopsToExport();
break;
case 2:
try { removeDialog(DIALOG_SELECT_ARCHIVE_NAME); } catch(Exception e) {}
try {
removeDialog(DIALOG_SELECT_ARCHIVE_NAME);
} catch (Exception e) {
}
showDialog(DIALOG_SELECT_ARCHIVE_NAME);
break;
case 3:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Uri uri = FileProvider.getUriForFile(new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName));
Uri uri = FileProvider.getUriForFile(new File(FileUtils.LL_EXT_DIR + "/" + mArchiveName));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("application/zip");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.br_s)));
break;
case 4:
try { removeDialog(DIALOG_CONFIRM_DELETE); } catch(Exception e) {}
try {
removeDialog(DIALOG_CONFIRM_DELETE);
} catch (Exception e) {
}
showDialog(DIALOG_CONFIRM_DELETE);
break;
}
@ -372,7 +378,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
}
private void loadArchive(Uri archiveUri, String archiveName) {
if(LLApp.get().isTrialVersion()) {
if (LLApp.get().isTrialVersion()) {
LLApp.get().showFeatureLockedDialog(this);
} else {
mArchiveUri = archiveUri;
@ -391,57 +397,60 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
showDialog(DIALOG_SELECT_BACKUP_ACTION);
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_SELECT_PAGES_FOR_EXPORT) {
if(resultCode == RESULT_OK) {
if (requestCode == REQUEST_SELECT_PAGES_FOR_EXPORT) {
if (resultCode == RESULT_OK) {
int[] selected_pages = data.getIntArrayExtra(API.SCREEN_PICKER_INTENT_EXTRA_SELECTED_SCREENS);
ArrayList<Integer> all_pages = new ArrayList<Integer>();
for(int p : selected_pages) {
all_pages.add(Integer.valueOf(p));
addSubPages(all_pages, p);
for (int p : selected_pages) {
all_pages.add(Integer.valueOf(p));
addSubPages(all_pages, p);
}
all_pages.add(Integer.valueOf(Page.APP_DRAWER_PAGE));
all_pages.add(Integer.valueOf(Page.USER_MENU_PAGE));
doExportTemplate(mArchiveName, all_pages);
}
} else if(requestCode == REQUEST_SELECT_FILE_TO_IMPORT){
if(resultCode == RESULT_OK) {
importFile(data.getData());
} else if (requestCode == REQUEST_SELECT_FILE_TO_IMPORT) {
if (resultCode == RESULT_OK) {
importFile(data.getData());
}
} else if(requestCode == REQUEST_SELECT_FILE_TO_LOAD){
if(resultCode == RESULT_OK) {
loadArchive(data.getData(), null);
} else if (requestCode == REQUEST_SELECT_FILE_TO_LOAD) {
if (resultCode == RESULT_OK) {
loadArchive(data.getData(), null);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void addSubPages(ArrayList<Integer> all_pages, int p) {
Page page = LLApp.get().getAppEngine().getOrLoadPage(p);
for(Item i : page.items) {
if(i instanceof Folder) {
int folder_page_id = ((Folder)i).getFolderPageId();
all_pages.add(Integer.valueOf(folder_page_id));
addSubPages(all_pages, folder_page_id);
}
}
for (Item i : page.items) {
if (i instanceof Folder) {
int folder_page_id = ((Folder) i).getFolderPageId();
all_pages.add(Integer.valueOf(folder_page_id));
addSubPages(all_pages, folder_page_id);
}
}
}
private void exportArchive(boolean for_backup) {
mSelectArchiveNameForBackup = for_backup;
mArchiveName = null;
try { removeDialog(DIALOG_SELECT_ARCHIVE_NAME); } catch(Exception e) {}
mSelectArchiveNameForBackup = for_backup;
mArchiveName = null;
try {
removeDialog(DIALOG_SELECT_ARCHIVE_NAME);
} catch (Exception e) {
}
showDialog(DIALOG_SELECT_ARCHIVE_NAME);
}
private void selectDesktopsToExport() {
Intent intent = new Intent(this, ScreenManager.class);
private void selectDesktopsToExport() {
Intent intent = new Intent(this, ScreenManager.class);
intent.putExtra(API.SCREEN_PICKER_INTENT_EXTRA_SELECTED_SCREENS, LLApp.get().getAppEngine().getGlobalConfig().screensOrder);
intent.putExtra(API.SCREEN_PICKER_INTENT_EXTRA_TITLE, getString(R.string.tmpl_s_p));
startActivityForResult(intent, REQUEST_SELECT_PAGES_FOR_EXPORT);
@ -465,27 +474,27 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
@Override
protected Boolean doInBackground(Void... voids) {
BackupRestoreTool.BackupConfig backup_config=new BackupRestoreTool.BackupConfig();
BackupRestoreTool.BackupConfig backup_config = new BackupRestoreTool.BackupConfig();
backup_config.context=BackupRestore.this;
PackageManager pm=getPackageManager();
backup_config.context = BackupRestore.this;
PackageManager pm = getPackageManager();
try {
PackageInfo pi=pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir=pi.applicationInfo.dataDir+"/files";
backup_config.pathFrom=data_dir;
} catch(PackageManager.NameNotFoundException e) {
PackageInfo pi = pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir = pi.applicationInfo.dataDir + "/files";
backup_config.pathFrom = data_dir;
} catch (PackageManager.NameNotFoundException e) {
// pass
}
backup_config.pathTo=backup_path;
backup_config.includeWidgetsData=true;
backup_config.includeWallpaper=true;
backup_config.includeFonts=true;
backup_config.forTemplate =true;
backup_config.pathTo = backup_path;
backup_config.includeWidgetsData = true;
backup_config.includeWallpaper = true;
backup_config.includeFonts = true;
backup_config.forTemplate = true;
backup_config.statusBarHeight = sb_height;
backup_config.pagesToInclude = included_pages;
return BackupRestoreTool.backup(backup_config)==null;
return BackupRestoreTool.backup(backup_config) == null;
}
@Override
@ -496,140 +505,10 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
}
}.execute((Void) null);
}
private class BackupTask extends AsyncTask<String, Void, Exception> {
private String mBackupFilePath;
@Override
protected void onPreExecute() {
showDialog(DIALOG_BACKUP_IN_PROGRESS);
}
@Override
protected Exception doInBackground(String... params) {
mBackupFilePath=(String)params[0];
BackupRestoreTool.BackupConfig backup_config=new BackupRestoreTool.BackupConfig();
backup_config.context=BackupRestore.this;
PackageManager pm=getPackageManager();
try {
PackageInfo pi=pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir=pi.applicationInfo.dataDir+"/files";
backup_config.pathFrom=data_dir;
} catch(PackageManager.NameNotFoundException e) {
// pass
}
backup_config.pathTo=mBackupFilePath;
backup_config.includeWidgetsData=true;
backup_config.includeWallpaper=true;
backup_config.includeFonts=true;
return BackupRestoreTool.backup(backup_config);
}
@Override
protected void onPostExecute(Exception result) {
removeDialog(DIALOG_BACKUP_IN_PROGRESS);
if(result != null) {
Writer out = new StringWriter(1000);
PrintWriter printWriter = new PrintWriter(out);
result.printStackTrace(printWriter);
Intent email_intent=new Intent(android.content.Intent.ACTION_SEND, Uri.parse("mailto:"));
email_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
email_intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"pierrox@pierrox.net"});
email_intent.putExtra(Intent.EXTRA_SUBJECT, "Backup error");
email_intent.putExtra(Intent.EXTRA_TEXT, out.toString());
email_intent.setType("message/rfc822");
startActivity(Intent.createChooser(email_intent, "Backup error, please send a bug report by email"));
}
String msg=(result==null ? getString(R.string.backup_done, mBackupFilePath) : getString(R.string.backup_error));
Toast.makeText(BackupRestore.this, msg, Toast.LENGTH_LONG).show();
loadArchivesList();
}
}
private class RestoreTask extends AsyncTask<String, Void, Integer> {
private Uri mUri;
private RestoreTask(String path) {
mUri = Uri.fromFile(new File(path));
}
private RestoreTask(Uri uri) {
mUri = uri;
}
@Override
protected void onPreExecute() {
showDialog(DIALOG_RESTORE_IN_PROGRESS);
}
@Override
protected Integer doInBackground(String... params) {
BackupRestoreTool.RestoreConfig restore_config=new BackupRestoreTool.RestoreConfig();
InputStream is = null;
try {
ContentResolver cr = getContentResolver();
is = cr.openInputStream(mUri);
JSONObject manifest = BackupRestoreTool.readManifest(is);
if(manifest != null) {
// it looks like a template
return 2;
}
} catch(Exception e) {
// not a template, continue with normal restore
} finally {
if(is != null) try { is.close(); } catch (IOException e) {}
}
restore_config.context=BackupRestore.this;
PackageManager pm=getPackageManager();
try {
PackageInfo pi=pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir=pi.applicationInfo.dataDir+"/files";
restore_config.pathTo=data_dir;
} catch(PackageManager.NameNotFoundException e) {
// pass
}
restore_config.uriFrom=mUri;
restore_config.restoreWidgetsData=true;
restore_config.restoreWallpaper=true;
restore_config.restoreFonts=true;
// ensure this directory at least is created with right permissions
try {
restore_config.context.createPackageContext(BackupRestore.this.getPackageName(), 0).getDir("files", Context.MODE_PRIVATE);
} catch (PackageManager.NameNotFoundException e1) {
return 0;
}
return BackupRestoreTool.restore(restore_config) ? 1 : 0;
}
@Override
protected void onPostExecute(Integer result) {
removeDialog(DIALOG_RESTORE_IN_PROGRESS);
if(result == 1) {
startActivity(new Intent(BackupRestore.this, Dashboard.class));
System.exit(0);
} else if(result == 2) {
Intent intent = new Intent(BackupRestore.this, ApplyTemplate.class);
intent.putExtra(ApplyTemplate.INTENT_EXTRA_URI, mUri);
startActivity(intent);
finish();
} else {
Toast.makeText(BackupRestore.this, R.string.restore_error, Toast.LENGTH_LONG).show();
}
}
}
/**
* Request the user to pick an archive.
*
* @param only_load true to directly load the archive without first importing it in the LL_EXT_DIR directory.
*/
private void selectFileToLoadOrImport(boolean only_load) {
@ -666,20 +545,26 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
FileUtils.copyStream(is, os);
return outFile;
} catch (IOException e) {
if(outFile != null) {
if (outFile != null) {
outFile.delete();
}
return null;
} finally {
try { if(is != null) is.close(); } catch(IOException e) {}
try { if(os != null) os.close(); } catch(IOException e) {}
try {
if (is != null) is.close();
} catch (IOException e) {
}
try {
if (os != null) os.close();
} catch (IOException e) {
}
}
}
@Override
protected void onPostExecute(File outFile) {
mDialog.dismiss();
if(outFile != null) {
if (outFile != null) {
loadArchivesList();
loadArchive(null, outFile.getName());
} else {
@ -706,4 +591,139 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
}
return name;
}
private class BackupTask extends AsyncTask<String, Void, Exception> {
private String mBackupFilePath;
@Override
protected void onPreExecute() {
showDialog(DIALOG_BACKUP_IN_PROGRESS);
}
@Override
protected Exception doInBackground(String... params) {
mBackupFilePath = params[0];
BackupRestoreTool.BackupConfig backup_config = new BackupRestoreTool.BackupConfig();
backup_config.context = BackupRestore.this;
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir = pi.applicationInfo.dataDir + "/files";
backup_config.pathFrom = data_dir;
} catch (PackageManager.NameNotFoundException e) {
// pass
}
backup_config.pathTo = mBackupFilePath;
backup_config.includeWidgetsData = true;
backup_config.includeWallpaper = true;
backup_config.includeFonts = true;
return BackupRestoreTool.backup(backup_config);
}
@Override
protected void onPostExecute(Exception result) {
removeDialog(DIALOG_BACKUP_IN_PROGRESS);
if (result != null) {
Writer out = new StringWriter(1000);
PrintWriter printWriter = new PrintWriter(out);
result.printStackTrace(printWriter);
Intent email_intent = new Intent(android.content.Intent.ACTION_SEND, Uri.parse("mailto:"));
email_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
email_intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"pierrox@pierrox.net"});
email_intent.putExtra(Intent.EXTRA_SUBJECT, "Backup error");
email_intent.putExtra(Intent.EXTRA_TEXT, out.toString());
email_intent.setType("message/rfc822");
startActivity(Intent.createChooser(email_intent, "Backup error, please send a bug report by email"));
}
String msg = (result == null ? getString(R.string.backup_done, mBackupFilePath) : getString(R.string.backup_error));
Toast.makeText(BackupRestore.this, msg, Toast.LENGTH_LONG).show();
loadArchivesList();
}
}
private class RestoreTask extends AsyncTask<String, Void, Integer> {
private final Uri mUri;
private RestoreTask(String path) {
mUri = Uri.fromFile(new File(path));
}
private RestoreTask(Uri uri) {
mUri = uri;
}
@Override
protected void onPreExecute() {
showDialog(DIALOG_RESTORE_IN_PROGRESS);
}
@Override
protected Integer doInBackground(String... params) {
BackupRestoreTool.RestoreConfig restore_config = new BackupRestoreTool.RestoreConfig();
InputStream is = null;
try {
ContentResolver cr = getContentResolver();
is = cr.openInputStream(mUri);
JSONObject manifest = BackupRestoreTool.readManifest(is);
if (manifest != null) {
// it looks like a template
return 2;
}
} catch (Exception e) {
// not a template, continue with normal restore
} finally {
if (is != null) try {
is.close();
} catch (IOException e) {
}
}
restore_config.context = BackupRestore.this;
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir = pi.applicationInfo.dataDir + "/files";
restore_config.pathTo = data_dir;
} catch (PackageManager.NameNotFoundException e) {
// pass
}
restore_config.uriFrom = mUri;
restore_config.restoreWidgetsData = true;
restore_config.restoreWallpaper = true;
restore_config.restoreFonts = true;
// ensure this directory at least is created with right permissions
try {
restore_config.context.createPackageContext(BackupRestore.this.getPackageName(), 0).getDir("files", Context.MODE_PRIVATE);
} catch (PackageManager.NameNotFoundException e1) {
return 0;
}
return BackupRestoreTool.restore(restore_config) ? 1 : 0;
}
@Override
protected void onPostExecute(Integer result) {
removeDialog(DIALOG_RESTORE_IN_PROGRESS);
if (result == 1) {
startActivity(new Intent(BackupRestore.this, Dashboard.class));
System.exit(0);
} else if (result == 2) {
Intent intent = new Intent(BackupRestore.this, ApplyTemplate.class);
intent.putExtra(ApplyTemplate.INTENT_EXTRA_URI, mUri);
startActivity(intent);
finish();
} else {
Toast.makeText(BackupRestore.this, R.string.restore_error, Toast.LENGTH_LONG).show();
}
}
}
}

View file

@ -91,6 +91,35 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
private boolean mEventActionForPickNew;
private LightningEngine mAppEngine;
public static void startActivityForResult(Activity activity, EventAction ea, boolean forItem, int type, boolean forShortcut, int requestCode) {
Intent intent = new Intent(activity, EventActionSetup.class);
intent.putExtra(INTENT_EXTRA_FOR_ITEM, forItem);
intent.putExtra(INTENT_EXTRA_FOR_SHORTCUT, forShortcut);
intent.putExtra(INTENT_EXTRA_TYPE, type);
if (ea != null) {
JSONObject out = new JSONObject();
JsonLoader.toJSONObject(out, ea, null);
intent.putExtra(INTENT_EXTRA_EVENT_ACTION_LIST, out.toString());
}
activity.startActivityForResult(intent, requestCode);
}
public static EventAction getEventActionFromIntent(Intent intent) {
String s = intent.getStringExtra(INTENT_EXTRA_EVENT_ACTION_LIST);
if (s != null) {
try {
JSONObject json = new JSONObject(s);
EventAction ea = new EventAction();
JsonLoader.loadFieldsFromJSONObject(ea, json, null);
return ea;
} catch (JSONException e) {
// pass
}
}
return null;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR);
@ -107,12 +136,12 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
mType = intent.getIntExtra(INTENT_EXTRA_TYPE, Action.FLAG_TYPE_DESKTOP);
String s;
if(savedInstanceState != null) {
if (savedInstanceState != null) {
s = savedInstanceState.getString(INTENT_EXTRA_EVENT_ACTION_LIST);
String p = savedInstanceState.getString(SIS_EVENT_ACTION_PICK);
mEventActionForPickNew = savedInstanceState.getBoolean(SIS_EVENT_ACTION_PICK_NEW);
if(p != null) {
if (p != null) {
mEventActionForPick = new EventAction();
try {
JsonLoader.loadFieldsFromJSONObject(mEventActionForPick, new JSONObject(p), null);
@ -161,13 +190,13 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
Window window = getWindow();
window.setBackgroundDrawable(decorView.getBackground());
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
View dialogContent = ((ViewGroup)decorView.findViewById(android.R.id.content)).getChildAt(0);
((ViewGroup)dialogContent.getParent()).removeView(dialogContent);
View dialogContent = ((ViewGroup) decorView.findViewById(android.R.id.content)).getChildAt(0);
((ViewGroup) dialogContent.getParent()).removeView(dialogContent);
dialog.dismiss();
setContentView(dialogContent);
final DragSortListView list = (DragSortListView) dialogContent.findViewById(android.R.id.list);
final DragSortListView list = dialogContent.findViewById(android.R.id.list);
mAdapter = new EventActionAdapter(this, mEventActions);
list.setAdapter(mAdapter);
list.setOnItemClickListener(this);
@ -196,7 +225,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
}
});
if(mEventActions.size() == 0) {
if (mEventActions.size() == 0) {
addAction();
}
}
@ -212,41 +241,12 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
outState.putString(INTENT_EXTRA_EVENT_ACTION_LIST, serializeEventAction());
if(mEventActionForPick != null) {
if (mEventActionForPick != null) {
outState.putString(SIS_EVENT_ACTION_PICK, JsonLoader.toJSONObject(mEventActionForPick, null).toString());
outState.putBoolean(SIS_EVENT_ACTION_PICK_NEW, mEventActionForPickNew);
}
}
public static void startActivityForResult(Activity activity, EventAction ea, boolean forItem, int type, boolean forShortcut, int requestCode) {
Intent intent = new Intent(activity, EventActionSetup.class);
intent.putExtra(INTENT_EXTRA_FOR_ITEM, forItem);
intent.putExtra(INTENT_EXTRA_FOR_SHORTCUT, forShortcut);
intent.putExtra(INTENT_EXTRA_TYPE, type);
if(ea != null) {
JSONObject out = new JSONObject();
JsonLoader.toJSONObject(out, ea, null);
intent.putExtra(INTENT_EXTRA_EVENT_ACTION_LIST, out.toString());
}
activity.startActivityForResult(intent, requestCode);
}
public static EventAction getEventActionFromIntent(Intent intent) {
String s = intent.getStringExtra(INTENT_EXTRA_EVENT_ACTION_LIST);
if(s != null) {
try {
JSONObject json = new JSONObject(s);
EventAction ea = new EventAction();
JsonLoader.loadFieldsFromJSONObject(ea, json, null);
return ea;
} catch (JSONException e) {
// pass
}
}
return null;
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
editAction(mAdapter.getItem(i), false);
@ -254,14 +254,14 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
private void deserializeEventActionList(String s) {
mEventActions = new ArrayList<>();
if(s != null) {
if (s != null) {
try {
JSONObject json = new JSONObject(s);
EventAction ea = new EventAction();
JsonLoader.loadFieldsFromJSONObject(ea, json, null);
while(ea != null) {
if(ea.action != GlobalConfig.UNSET) {
while (ea != null) {
if (ea.action != GlobalConfig.UNSET) {
mEventActions.add(ea);
}
EventAction ea_tmp = ea.next;
@ -278,8 +278,8 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
EventAction current = null;
EventAction first = null;
for (EventAction ea : mEventActions) {
if(ea.action == GlobalConfig.UNSET) continue;
if(current == null) {
if (ea.action == GlobalConfig.UNSET) continue;
if (current == null) {
current = ea;
first = ea;
} else {
@ -288,7 +288,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
}
}
if(first == null) {
if (first == null) {
first = new EventAction(GlobalConfig.UNSET, null);
}
JSONObject out = JsonLoader.toJSONObject(first, null);
@ -304,7 +304,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
private void saveAndFinish() {
String serializedEventAction = serializeEventAction();
Intent intent;
if(mForShortcut) {
if (mForShortcut) {
Intent i = new Intent(this, Dashboard.class);
i.putExtra(LightningIntent.INTENT_EXTRA_EVENT_ACTION, serializedEventAction);
String name = mActions.getActionName(mEventActions.size() == 0 ? GlobalConfig.UNSET : mEventActions.get(0).action);
@ -352,7 +352,10 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
Intent i = new Intent(Intent.ACTION_PICK_ACTIVITY);
i.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT));
i.putExtra(Intent.EXTRA_TITLE, getString(R.string.tools_pick_shortcut));
try { startActivityForResult(i, REQUEST_PICK_SHORTCUT1); } catch (Exception e) { }
try {
startActivityForResult(i, REQUEST_PICK_SHORTCUT1);
} catch (Exception e) {
}
} else if (new_action == GlobalConfig.RUN_SCRIPT) {
ScriptPickerDialog dialog = new ScriptPickerDialog(this, mAppEngine, ea.data, Script.TARGET_NONE, new ScriptPickerDialog.OnScriptPickerEvent() {
@Override
@ -363,7 +366,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
@Override
public void onScriptPickerCanceled() {
if(mEventActionForPickNew) {
if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged();
}
@ -380,7 +383,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
@Override
public void onNoFolderSelected() {
if(mEventActionForPickNew) {
if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged();
}
@ -401,7 +404,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
@Override
public void onSetVariableCancel() {
if(mEventActionForPickNew) {
if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged();
}
@ -416,7 +419,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
if (resultCode == RESULT_OK) {
startActivityForResult(data, REQUEST_PICK_SHORTCUT2);
} else {
if(mEventActionForPickNew) {
if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged();
}
@ -431,7 +434,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
e.printStackTrace();
}
} else {
if(mEventActionForPickNew) {
if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged();
}
@ -441,58 +444,11 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
}
}
private class EventActionAdapter extends ArrayAdapter<EventAction> implements View.OnClickListener {
public EventActionAdapter(Context context, List<EventAction> objects) {
super(context, 0, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.event_action_item, parent, false);
TextView drag = (TextView) convertView.findViewById(R.id.drag);
drag.setTypeface(LLApp.get().getIconsTypeface());
TextView delete = (TextView) convertView.findViewById(R.id.delete);
delete.setOnClickListener(this);
delete.setTypeface(LLApp.get().getIconsTypeface());
}
EventAction ea = getItem(position);
TextView title = (TextView) convertView.findViewById(android.R.id.text1);
title.setText(mActions.getActionName(ea.action));
String summaryText = ea.describe(mAppEngine);
TextView summary = (TextView) convertView.findViewById(android.R.id.text2);
if(summaryText == null) {
title.setSingleLine(false);
title.setMaxLines(2);
summary.setVisibility(View.GONE);
} else {
title.setSingleLine(true);
summary.setVisibility(View.VISIBLE);
summary.setText(summaryText);
}
convertView.findViewById(R.id.delete).setTag(ea);
return convertView;
}
@Override
public void onClick(View view) {
EventAction ea = (EventAction) view.getTag();
mEventActions.remove(ea);
mAdapter.notifyDataSetChanged();
}
}
private static class ActionsAdapter extends ArrayAdapter<Action> {
private final LayoutInflater mInflater;
private int mPrefLayout;
private int mPrefCategoryLayout;
private final int mPrefLayout;
private final int mPrefCategoryLayout;
public ActionsAdapter(Context context, ActionsDescription actionsDescription) {
super(context, 0, filterActions(actionsDescription));
@ -508,7 +464,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
ArrayList<Action> filteredActions = new ArrayList<>(actions.size());
for (Action action : actions) {
if(action.action != GlobalConfig.UNSET) {
if (action.action != GlobalConfig.UNSET) {
filteredActions.add(action);
}
}
@ -530,21 +486,68 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position);
boolean isCategory = action.action == GlobalConfig.CATEGORY;
if(convertView == null) {
if (convertView == null) {
convertView = mInflater.inflate(isCategory ? mPrefCategoryLayout : mPrefLayout, parent, false);
}
TextView title_view = (TextView) convertView.findViewById(android.R.id.title);
TextView title_view = convertView.findViewById(android.R.id.title);
title_view.setText(action.label);
if(!isCategory) {
if (!isCategory) {
title_view.setSingleLine(false);
title_view.setMaxLines(2);
convertView.findViewById(android.R.id.summary).setVisibility(View.GONE);
View icon = convertView.findViewById(android.R.id.icon);
if(icon != null) icon.setVisibility(View.GONE);
if (icon != null) icon.setVisibility(View.GONE);
}
return convertView;
}
}
private class EventActionAdapter extends ArrayAdapter<EventAction> implements View.OnClickListener {
public EventActionAdapter(Context context, List<EventAction> objects) {
super(context, 0, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.event_action_item, parent, false);
TextView drag = convertView.findViewById(R.id.drag);
drag.setTypeface(LLApp.get().getIconsTypeface());
TextView delete = convertView.findViewById(R.id.delete);
delete.setOnClickListener(this);
delete.setTypeface(LLApp.get().getIconsTypeface());
}
EventAction ea = getItem(position);
TextView title = convertView.findViewById(android.R.id.text1);
title.setText(mActions.getActionName(ea.action));
String summaryText = ea.describe(mAppEngine);
TextView summary = convertView.findViewById(android.R.id.text2);
if (summaryText == null) {
title.setSingleLine(false);
title.setMaxLines(2);
summary.setVisibility(View.GONE);
} else {
title.setSingleLine(true);
summary.setVisibility(View.VISIBLE);
summary.setText(summaryText);
}
convertView.findViewById(R.id.delete).setTag(ea);
return convertView;
}
@Override
public void onClick(View view) {
EventAction ea = (EventAction) view.getTag();
mEventActions.remove(ea);
mAdapter.notifyDataSetChanged();
}
}
}

View file

@ -37,7 +37,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
@ -59,6 +58,12 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
private TextView mSelectionText;
private CropperView mCropperView;
public static void startActivity(Activity from, File image, int requestCode) {
final Intent intent = new Intent(from, ImageCropper.class);
intent.putExtra(INTENT_EXTRA_IMAGE, image.getAbsolutePath());
from.startActivityForResult(intent, requestCode);
}
@Override
public void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR);
@ -66,14 +71,14 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
setContentView(R.layout.image_cropper);
mSelectionText = (TextView) findViewById(R.id.sr);
mSelectionText = findViewById(R.id.sr);
mCropperView = (CropperView) findViewById(R.id.cv);
mCropperView = findViewById(R.id.cv);
Bitmap bitmap;
Intent intent = getIntent();
String sourcePath = intent.getStringExtra(INTENT_EXTRA_IMAGE);
mSourceFile = new File(sourcePath);
if(intent.getBooleanExtra(INTENT_EXTRA_FULL_SIZE, false)) {
if (intent.getBooleanExtra(INTENT_EXTRA_FULL_SIZE, false)) {
bitmap = Utils.loadBitmap(mSourceFile, 0, 0, 0);
} else {
bitmap = Utils.loadScreenSizedBitmap(getWindowManager(), sourcePath);
@ -87,16 +92,16 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
@Override
public void onClick(View v) {
switch(v.getId()) {
switch (v.getId()) {
case R.id.ok:
final Rect r = mCropperView.getSelection();
final Bitmap original_image = ((BitmapDrawable)mCropperView.getDrawable()).getBitmap();
final Bitmap original_image = ((BitmapDrawable) mCropperView.getDrawable()).getBitmap();
final File destinationFile = Utils.getTmpImageFile();
if(r.left == 0 && r.top == 0 && r.width() == original_image.getWidth() && r.height() == original_image.getHeight()) {
if (r.left == 0 && r.top == 0 && r.width() == original_image.getWidth() && r.height() == original_image.getHeight()) {
boolean success;
// full image size: no cropping
if(mSourceFile.compareTo(destinationFile) == 0) {
if (mSourceFile.compareTo(destinationFile) == 0) {
// same file, nothing to do
success = true;
} else {
@ -159,7 +164,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
private void done(boolean success) {
setResult(success ? RESULT_OK : RESULT_CANCELED);
if(!success) {
if (!success) {
Toast.makeText(this, R.string.tr_eu, Toast.LENGTH_SHORT).show();
}
finish();
@ -167,7 +172,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
@Override
public void onCropperViewSelectionChanged(Rect selection) {
mSelectionText.setText(selection.toShortString()+" ("+selection.width()+"px x "+selection.height()+"px)");
mSelectionText.setText(selection.toShortString() + " (" + selection.width() + "px x " + selection.height() + "px)");
}
@Override
@ -178,18 +183,18 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
View content = getLayoutInflater().inflate(R.layout.dialog_rect, null);
builder.setTitle(getString(R.string.rect));
builder.setView(content);
((TextView)content.findViewById(R.id.rect_l)).setText(getString(R.string.left));
((TextView)content.findViewById(R.id.rect_t)).setText(getString(R.string.top));
((TextView)content.findViewById(R.id.rect_r)).setText(getString(R.string.right));
((TextView)content.findViewById(R.id.rect_b)).setText(getString(R.string.bottom));
((TextView)content.findViewById(R.id.rect_w)).setText(getString(R.string.gb_w).toLowerCase());
((TextView)content.findViewById(R.id.rect_h)).setText(getString(R.string.gb_h).toLowerCase());
final EditText el = (EditText)content.findViewById(R.id.rect_el);
final EditText et = (EditText)content.findViewById(R.id.rect_et);
final EditText er = (EditText)content.findViewById(R.id.rect_er);
final EditText eb = (EditText)content.findViewById(R.id.rect_eb);
final EditText ew = (EditText)content.findViewById(R.id.rect_ew);
final EditText eh = (EditText)content.findViewById(R.id.rect_eh);
((TextView) content.findViewById(R.id.rect_l)).setText(getString(R.string.left));
((TextView) content.findViewById(R.id.rect_t)).setText(getString(R.string.top));
((TextView) content.findViewById(R.id.rect_r)).setText(getString(R.string.right));
((TextView) content.findViewById(R.id.rect_b)).setText(getString(R.string.bottom));
((TextView) content.findViewById(R.id.rect_w)).setText(getString(R.string.gb_w).toLowerCase());
((TextView) content.findViewById(R.id.rect_h)).setText(getString(R.string.gb_h).toLowerCase());
final EditText el = content.findViewById(R.id.rect_el);
final EditText et = content.findViewById(R.id.rect_et);
final EditText er = content.findViewById(R.id.rect_er);
final EditText eb = content.findViewById(R.id.rect_eb);
final EditText ew = content.findViewById(R.id.rect_ew);
final EditText eh = content.findViewById(R.id.rect_eh);
el.setText(String.valueOf(selection.left));
et.setText(String.valueOf(selection.top));
er.setText(String.valueOf(selection.right));
@ -213,7 +218,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int r = Integer.parseInt(er.getText().toString());
int w = Integer.parseInt(ew.getText().toString());
int new_w = r - l;
if(new_w != w) {
if (new_w != w) {
ew.setText(String.valueOf(new_w));
}
} catch (NumberFormatException e) {
@ -238,7 +243,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int b = Integer.parseInt(eb.getText().toString());
int h = Integer.parseInt(eh.getText().toString());
int new_h = b - t;
if(new_h != h) {
if (new_h != h) {
eh.setText(String.valueOf(new_h));
}
} catch (NumberFormatException e) {
@ -263,7 +268,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int r = Integer.parseInt(er.getText().toString());
int w = Integer.parseInt(ew.getText().toString());
int new_r = l + w;
if(new_r != r) {
if (new_r != r) {
er.setText(String.valueOf(new_r));
}
} catch (NumberFormatException e) {
@ -288,7 +293,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int h = Integer.parseInt(eh.getText().toString());
int b = Integer.parseInt(eb.getText().toString());
int new_b = t + h;
if(new_b != b) {
if (new_b != b) {
eb.setText(String.valueOf(new_b));
}
} catch (NumberFormatException e) {
@ -314,7 +319,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int b = Integer.parseInt(eb.getText().toString());
selection.set(l, t, r, b);
mCropperView.setSelection(selection);
} catch(NumberFormatException e) {
} catch (NumberFormatException e) {
}
}
@ -322,10 +327,4 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
builder.setNegativeButton(android.R.string.cancel, null);
builder.create().show();
}
public static void startActivity(Activity from, File image, int requestCode) {
final Intent intent = new Intent(from, ImageCropper.class);
intent.putExtra(INTENT_EXTRA_IMAGE, image.getAbsolutePath());
from.startActivityForResult(intent, requestCode);
}
}

View file

@ -24,6 +24,8 @@ SOFTWARE.
package net.pierrox.lightning_launcher.activities;
import static android.content.ClipData.newPlainText;
import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
@ -47,7 +49,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
@ -88,8 +89,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static android.content.ClipData.newPlainText;
public class ImagePicker extends ResourceWrapperActivity implements AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener, View.OnClickListener, ColorPickerDialog.OnColorChangedListener, View.OnLongClickListener, AdapterView.OnItemLongClickListener, EditTextIme.OnEditTextImeListener, TextWatcher {
private static final int MODE_NONE = -1;
@ -151,25 +150,21 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
private int mLauncherIconDensity;
private View mClickedView;
private static class BitmapInfo {
Bitmap bitmap;
boolean isNinePatch; // need to be stored because 9patch chunk is lost during resize
private BitmapInfo(Bitmap bitmap, boolean isNinePatch) {
this.bitmap = bitmap;
this.isNinePatch = isNinePatch;
}
}
private LruCache<String, BitmapInfo> mThumbnailCache;
public static void startActivity(Activity from, int requestCode) {
final Intent intent = new Intent(from, ImagePicker.class);
intent.putExtra(INTENT_EXTRA_CROP, true);
from.startActivityForResult(intent, requestCode);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR);
super.onCreate(savedInstanceState);
if(savedInstanceState == null) {
if (savedInstanceState == null) {
// if recreated because the activity has been disposed by the framework, don't remove
// the temp file, it will be used for instance in the activity result callback
Utils.getTmpImageFile().delete();
@ -191,14 +186,14 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
protected int sizeOf(String key, BitmapInfo bitmapInfo) {
// The cache size will be measured in kilobytes rather than
// number of items.
if(finalGetByteCount != null) {
if (finalGetByteCount != null) {
try {
return (Integer)finalGetByteCount.invoke(bitmapInfo.bitmap) / 1024;
return (Integer) finalGetByteCount.invoke(bitmapInfo.bitmap) / 1024;
} catch (Exception e) {
// pass and continue
}
}
return bitmapInfo.bitmap.getWidth()*bitmapInfo.bitmap.getHeight() * 4 /1024;
return bitmapInfo.bitmap.getWidth() * bitmapInfo.bitmap.getHeight() * 4 / 1024;
}
};
@ -211,15 +206,15 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
d.setBounds(0, 0, mDefaultIcon.getWidth(), mDefaultIcon.getHeight());
d.draw(c);
mStandardIconSize =getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
mLauncherIconDensity =0;
mStandardIconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
mLauncherIconDensity = 0;
try {
Method getLauncherLargeIconSize=ActivityManager.class.getMethod("getLauncherLargeIconSize");
Method getLauncherLargeIconDensity=ActivityManager.class.getMethod("getLauncherLargeIconDensity");
ActivityManager am=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
mStandardIconSize =(Integer) getLauncherLargeIconSize.invoke(am, (Object[])null);
mLauncherIconDensity =(Integer) getLauncherLargeIconDensity.invoke(am, (Object[])null);
Method getLauncherLargeIconSize = ActivityManager.class.getMethod("getLauncherLargeIconSize");
Method getLauncherLargeIconDensity = ActivityManager.class.getMethod("getLauncherLargeIconDensity");
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
mStandardIconSize = (Integer) getLauncherLargeIconSize.invoke(am, (Object[]) null);
mLauncherIconDensity = (Integer) getLauncherLargeIconDensity.invoke(am, (Object[]) null);
} catch (Exception e) {
// pass API level 11, 15
}
@ -236,35 +231,33 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
mCurrentScrollLauncherPage = prefs.getInt(PREF_CURRENT_SCROLL_LAUNCHER_PAGE, 0);
setContentView(R.layout.image_picker);
mSourceSpinner = (Spinner) findViewById(R.id.source);
mSourceSpinner = findViewById(R.id.source);
ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.ip_s));
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSourceSpinner.setAdapter(adapter);
mSourceSpinner.setOnItemSelectedListener(this);
mIconPackSpinner = (Spinner) findViewById(R.id.icon_pack);
mIconPackSpinner = findViewById(R.id.icon_pack);
mIconPackSpinner.setOnItemSelectedListener(this);
mPkgSpinner = (Spinner) findViewById(R.id.pkg);
mPkgSpinner = findViewById(R.id.pkg);
mPkgSpinner.setOnItemSelectedListener(this);
mLauncherPageSpinner = (Spinner) findViewById(R.id.launcher_page);
mLauncherPageSpinner = findViewById(R.id.launcher_page);
mLauncherPageSpinner.setOnItemSelectedListener(this);
mPathTextGrp = findViewById(R.id.path_grp);
mPathTextView = (TextView) findViewById(R.id.path);
Button up = (Button)findViewById(R.id.path_up);
mPathTextView = findViewById(R.id.path);
Button up = findViewById(R.id.path_up);
up.setText(R.string.file_picker_activity_up);
up.setOnClickListener(this);
mNoIconTextView = (TextView) findViewById(R.id.no_icon);
mNoIconTextView = findViewById(R.id.no_icon);
mNoIconTextView.setText(R.string.ip_e);
mGridView = (GridView) findViewById(R.id.grid);
mGridView = findViewById(R.id.grid);
mGridView.setNumColumns(GridView.AUTO_FIT);
mGridView.setColumnWidth(mStandardIconSize * 2);
mGridView.setStretchMode(GridView.STRETCH_SPACING_UNIFORM);
@ -287,7 +280,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
mBackgroundColor = prefs.getInt(PREF_BACKGROUND_COLOR, Color.TRANSPARENT);
mGridView.setBackgroundColor(mBackgroundColor);
mSearchText = (EditTextIme) findViewById(R.id.search_text);
mSearchText = findViewById(R.id.search_text);
mSearchText.setOnEditTextImeListener(this);
mSearchText.addTextChangedListener(this);
@ -295,25 +288,25 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
Typeface typeface = LLApp.get().getIconsTypeface();
int[] ids = new int[] {
R.id.none,
R.id.ext_file,
R.id.camera,
R.id.bgcolor,
R.id.solid,
R.id.search
int[] ids = new int[]{
R.id.none,
R.id.ext_file,
R.id.camera,
R.id.bgcolor,
R.id.solid,
R.id.search
};
for(int id : ids) {
for (int id : ids) {
View v = findViewById(id);
v.setOnClickListener(this);
v.setOnLongClickListener(this);
((Button)v).setTypeface(typeface);
((Button) v).setTypeface(typeface);
}
if(mCurrentMode == MODE_ICON_PACK) {
if (mCurrentMode == MODE_ICON_PACK) {
mIconPackAdapter = new PkgLabelAdapter(this, true);
mIconPackSpinner.setAdapter(mIconPackAdapter);
if(mIconPackAdapter.getCount()==0) {
if (mIconPackAdapter.getCount() == 0) {
mCurrentMode = MODE_PKG;
}
}
@ -324,14 +317,14 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
checkPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
new int[] { R.string.pr_r4, R.string.pr_r5},
new int[]{R.string.pr_r4, R.string.pr_r5},
REQUEST_PERMISSION_BASE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(areAllPermissionsGranted(grantResults, R.string.pr_f3)) {
if(mCurrentMode == MODE_PATH) {
if (areAllPermissionsGranted(grantResults, R.string.pr_f3)) {
if (mCurrentMode == MODE_PATH) {
setMode(MODE_PATH);
}
}
@ -364,18 +357,18 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
// if(init == null) {
// adapterView.setTag(true);
// } else {
if (adapterView == mSourceSpinner) {
setMode(i);
} else if (adapterView == mIconPackSpinner) {
String pkg = mIconPackAdapter.getItem(i).pkg;
loadIconPack(pkg);
} else if (adapterView == mPkgSpinner) {
String pkg = mPkgAdapter.getItem(i).pkg;
loadPkg(pkg);
} else if (adapterView == mLauncherPageSpinner) {
String p = mLauncherPageAdapter.getItem(i);
loadLauncherPage(p);
}
if (adapterView == mSourceSpinner) {
setMode(i);
} else if (adapterView == mIconPackSpinner) {
String pkg = mIconPackAdapter.getItem(i).pkg;
loadIconPack(pkg);
} else if (adapterView == mPkgSpinner) {
String pkg = mPkgAdapter.getItem(i).pkg;
loadPkg(pkg);
} else if (adapterView == mLauncherPageSpinner) {
String p = mLauncherPageAdapter.getItem(i);
loadLauncherPage(p);
}
// }
}
@ -386,50 +379,50 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
if(adapterView == mGridView) {
if (adapterView == mGridView) {
byte[] buffer = new byte[4096];
Object item = mGridView.getItemAtPosition(position);
File tmp_image_file = Utils.getTmpImageFile();
if(mCurrentMode == MODE_PATH) {
if (mCurrentMode == MODE_PATH) {
ImageFile imf = (ImageFile) item;
if(imf.file.isDirectory()) {
if (imf.file.isDirectory()) {
loadPath(imf.file);
} else {
Utils.copyFileSafe(buffer, imf.file, tmp_image_file);
imagePicked(true);
}
} else if(mCurrentMode == MODE_PKG || mCurrentMode == MODE_ICON_PACK) {
} else if (mCurrentMode == MODE_PKG || mCurrentMode == MODE_ICON_PACK) {
ImageResource ir = (ImageResource) item;
FileOutputStream fos=null;
FileOutputStream fos = null;
InputStream is = null;
try {
Resources rsrc = ir.packageName.equals(ANDROID) ? getResources() : createPackageContext(ir.packageName, 0).getResources();
int id = ir.res;
boolean is_nine_patch = false;
Bitmap bmp = null;
if(Utils.sGetDrawableForDensity!=null) {
if (Utils.sGetDrawableForDensity != null) {
try {
BitmapDrawable d=(BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity);
BitmapDrawable d = (BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity);
Bitmap orig_bmp = d.getBitmap();
is_nine_patch = NinePatch.isNinePatchChunk(orig_bmp.getNinePatchChunk());
bmp = Utils.createStandardSizedIcon(orig_bmp, mStandardIconSize);
} catch(Throwable e) {
} catch (Throwable e) {
// pass, continue with classic method
}
}
if(bmp == null) {
if (bmp == null) {
bmp = BitmapFactory.decodeResource(rsrc, id);
if(bmp != null) {
if (bmp != null) {
is_nine_patch = NinePatch.isNinePatchChunk(bmp.getNinePatchChunk());
}
}
if(bmp != null) {
if(is_nine_patch) {
if (bmp != null) {
if (is_nine_patch) {
// nine patches need to be copied as is
is = rsrc.openRawResource(ir.res);
fos=new FileOutputStream(tmp_image_file);
fos = new FileOutputStream(tmp_image_file);
int n;
while((n=is.read(buffer))>0) {
while ((n = is.read(buffer)) > 0) {
fos.write(buffer, 0, n);
}
} else {
@ -445,10 +438,16 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
e.printStackTrace();
tmp_image_file.delete();
} finally {
if(is!=null) try { is.close(); } catch(Exception e) {}
if(fos!=null) try { fos.close(); } catch(Exception e) {}
if (is != null) try {
is.close();
} catch (Exception e) {
}
if (fos != null) try {
fos.close();
} catch (Exception e) {
}
}
} else if(mCurrentMode == MODE_LAUNCHER_PAGE) {
} else if (mCurrentMode == MODE_LAUNCHER_PAGE) {
ImageFile imf = (ImageFile) item;
Utils.copyFileSafe(buffer, imf.file, tmp_image_file);
imagePicked(true);
@ -461,15 +460,15 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
String label;
String clip_text;
Object item = adapterView.getItemAtPosition(i);
if(mCurrentMode == MODE_PATH || mCurrentMode == MODE_LAUNCHER_PAGE) {
if (mCurrentMode == MODE_PATH || mCurrentMode == MODE_LAUNCHER_PAGE) {
ImageFile f = (ImageFile) item;
label = f.file.getAbsolutePath();
clip_text = label;
} else {
ImageResource pkg = (ImageResource) item;
String s = pkg.packageName.equals(ANDROID) ? "android" : pkg.packageName;
label = s+"/"+pkg.label;
clip_text = "\""+s+"\", \""+pkg.label+"\"";
label = s + "/" + pkg.label;
clip_text = "\"" + s + "\", \"" + pkg.label + "\"";
}
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = newPlainText("llx", clip_text);
@ -487,7 +486,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
mClickedView = view;
final int id = view.getId();
switch(id) {
switch (id) {
case R.id.none:
Utils.getTmpImageFile().delete();
imagePicked(false);
@ -512,7 +511,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
case R.id.bgcolor:
case R.id.solid:
color_picker_dialog = new ColorPickerDialog(this, id ==R.id.bgcolor ? mBackgroundColor : Color.WHITE);
color_picker_dialog = new ColorPickerDialog(this, id == R.id.bgcolor ? mBackgroundColor : Color.WHITE);
color_picker_dialog.setAlphaSliderVisible(true);
color_picker_dialog.setOnColorChangedListener(this);
color_picker_dialog.show();
@ -524,7 +523,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
case R.id.path_up:
File parent = mCurrentPath.getParentFile();
if(parent != null) {
if (parent != null) {
loadPath(parent);
}
break;
@ -535,13 +534,25 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public boolean onLongClick(View view) {
int label_res = 0;
switch(view.getId()) {
case R.id.none: label_res = R.string.ip_none; break;
case R.id.ext_file: label_res = R.string.ip_ext_file; break;
case R.id.camera: label_res = R.string.ip_camera; break;
case R.id.bgcolor: label_res = R.string.ip_bgcolor; break;
case R.id.solid: label_res = R.string.ip_solid; break;
case R.id.search: label_res = R.string.ip_search; break;
switch (view.getId()) {
case R.id.none:
label_res = R.string.ip_none;
break;
case R.id.ext_file:
label_res = R.string.ip_ext_file;
break;
case R.id.camera:
label_res = R.string.ip_camera;
break;
case R.id.bgcolor:
label_res = R.string.ip_bgcolor;
break;
case R.id.solid:
label_res = R.string.ip_solid;
break;
case R.id.search:
label_res = R.string.ip_search;
break;
}
Toast.makeText(this, label_res, Toast.LENGTH_SHORT).show();
return true;
@ -551,13 +562,13 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CAPTURE_IMAGE:
if(resultCode == RESULT_OK) {
if (resultCode == RESULT_OK) {
imagePicked(true);
}
break;
case REQUEST_PICK_IMAGE:
if(resultCode == RESULT_OK) {
if (resultCode == RESULT_OK) {
FileOutputStream fos = null;
InputStream is = null;
try {
@ -565,21 +576,27 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
is = getContentResolver().openInputStream(data.getData());
byte[] buffer = new byte[4096];
int n;
while((n=is.read(buffer))>0) {
while ((n = is.read(buffer)) > 0) {
fos.write(buffer, 0, n);
}
imagePicked(true);
} catch(IOException e) {
} catch (IOException e) {
// pass
} finally {
if(fos != null) try { fos.close(); } catch(IOException e) {}
if(is != null) try { is.close(); } catch(IOException e) {}
if (fos != null) try {
fos.close();
} catch (IOException e) {
}
if (is != null) try {
is.close();
} catch (IOException e) {
}
}
}
break;
case REQUEST_CROP_IMAGE:
if(resultCode == RESULT_OK) {
if (resultCode == RESULT_OK) {
setResult(RESULT_OK);
finish();
}
@ -591,12 +608,6 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
}
public static void startActivity(Activity from, int requestCode) {
final Intent intent = new Intent(from, ImagePicker.class);
intent.putExtra(INTENT_EXTRA_CROP, true);
from.startActivityForResult(intent, requestCode);
}
private void setGridViewAdapter(ListAdapter adapter) {
mNoIconTextView.setVisibility(adapter == null || adapter.getCount() == 0 ? View.VISIBLE : View.GONE);
mGridView.setAdapter(adapter);
@ -609,25 +620,25 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
boolean launcher_page = false;
int pos = 0;
int count;
switch(mode) {
switch (mode) {
case MODE_ICON_PACK:
icon_pack = true;
if(mIconPackAdapter == null) {
if (mIconPackAdapter == null) {
mIconPackAdapter = new PkgLabelAdapter(this, true);
mIconPackSpinner.setAdapter(mIconPackAdapter);
}
if(mIconPackAdapter.getCount() == 0) {
if (mIconPackAdapter.getCount() == 0) {
setGridViewAdapter(null);
}
count = mIconPackAdapter.getCount();
for(int i=0; i<count; i++) {
if(mIconPackAdapter.getItem(i).pkg.equals(mCurrentIconPack)) {
for (int i = 0; i < count; i++) {
if (mIconPackAdapter.getItem(i).pkg.equals(mCurrentIconPack)) {
pos = i;
break;
}
}
if(mIconPackSpinner.getSelectedItemPosition() != pos) {
if (mIconPackSpinner.getSelectedItemPosition() != pos) {
mIconPackSpinner.setSelection(pos);
} else {
loadIconPack(mCurrentIconPack);
@ -643,17 +654,17 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
launcher_page = true;
File base_dir = LLApp.get().getAppEngine().getBaseDir();
ArrayList<String> pages = new ArrayList<String>();
if(mLauncherPageAdapter == null) {
for(int p = Page.FIRST_DASHBOARD_PAGE; p< Page.LAST_DASHBOARD_PAGE; p++) {
if (mLauncherPageAdapter == null) {
for (int p = Page.FIRST_DASHBOARD_PAGE; p < Page.LAST_DASHBOARD_PAGE; p++) {
File f = Page.getIconDir(base_dir, p);
if(f.exists()) {
if (f.exists()) {
pages.add(String.valueOf(p));
}
}
pages.add(String.valueOf(Page.APP_DRAWER_PAGE));
for(int p = Page.FIRST_FOLDER_PAGE; p< Page.LAST_FOLDER_PAGE; p++) {
for (int p = Page.FIRST_FOLDER_PAGE; p < Page.LAST_FOLDER_PAGE; p++) {
File f = Page.getIconDir(base_dir, p);
if(f.exists()) {
if (f.exists()) {
pages.add(String.valueOf(p));
}
}
@ -663,14 +674,14 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
count = mLauncherPageAdapter.getCount();
for(int i=0; i<count; i++) {
if(mLauncherPageAdapter.getItem(i).equals(mCurrentLauncherPage)) {
for (int i = 0; i < count; i++) {
if (mLauncherPageAdapter.getItem(i).equals(mCurrentLauncherPage)) {
pos = i;
break;
}
}
if(mLauncherPageSpinner.getSelectedItemPosition() != pos) {
if (mLauncherPageSpinner.getSelectedItemPosition() != pos) {
mLauncherPageSpinner.setSelection(pos);
} else {
loadLauncherPage(mCurrentLauncherPage);
@ -680,18 +691,18 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
case MODE_PKG:
pkg = true;
if(mPkgAdapter == null) {
if (mPkgAdapter == null) {
mPkgAdapter = new PkgLabelAdapter(this, false);
mPkgSpinner.setAdapter(mPkgAdapter);
}
count = mPkgAdapter.getCount();
for(int i=0; i<count; i++) {
if(mPkgAdapter.getItem(i).pkg.equals(mCurrentPkg)) {
for (int i = 0; i < count; i++) {
if (mPkgAdapter.getItem(i).pkg.equals(mCurrentPkg)) {
pos = i;
break;
}
}
if(mPkgSpinner.getSelectedItemPosition() != pos) {
if (mPkgSpinner.getSelectedItemPosition() != pos) {
mPkgSpinner.setSelection(pos);
} else {
loadPkg(mCurrentPkg);
@ -725,7 +736,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
File[] files = path.listFiles();
if(files != null) {
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
images.add(new ImageFile(f));
@ -805,8 +816,8 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
ArrayList<ImageResource> pkgs = new ArrayList<ImageResource>();
Resources rsrc = remoteContext.getResources();
int start = isAndroidPackage ? 0x01080000 : 0x7f020000;
int end = start+0x1000;
for(int i=start; i<end; i++) {
int end = start + 0x1000;
for (int i = start; i < end; i++) {
try {
String label = rsrc.getResourceEntryName(i);
@ -815,7 +826,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
ir.label = label;
ir.res = i;
pkgs.add(ir);
} catch(Resources.NotFoundException e) {
} catch (Resources.NotFoundException e) {
break;
}
}
@ -831,7 +842,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
private void storeGridViewScroll() {
if(mGridMode != MODE_NONE) {
if (mGridMode != MODE_NONE) {
int offset = mStandardIconSize / 3;
int index = mCurrentScrollIndex;//mGridView.getFirstVisiblePosition();
final View first = mGridView.getChildAt(0);
@ -839,19 +850,27 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
offset -= first.getTop();
}
int y = (index<<16) | offset;
int y = (index << 16) | offset;
switch (mGridMode) {
case MODE_PKG: mCurrentScrollPkg = y; break;
case MODE_PATH: mCurrentScrollPath = y; break;
case MODE_ICON_PACK: mCurrentScrollIconPack = y; break;
case MODE_LAUNCHER_PAGE: mCurrentScrollLauncherPage = y; break;
case MODE_PKG:
mCurrentScrollPkg = y;
break;
case MODE_PATH:
mCurrentScrollPath = y;
break;
case MODE_ICON_PACK:
mCurrentScrollIconPack = y;
break;
case MODE_LAUNCHER_PAGE:
mCurrentScrollLauncherPage = y;
break;
}
}
}
private void setGridViewScroll(int scroll) {
if(mGridMode == mCurrentMode) {
if (mGridMode == mCurrentMode) {
mGridView.setSelection(0);
} else {
mGridMode = mCurrentMode;
@ -862,7 +881,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public void onColorChanged(int color) {
switch(mClickedView.getId()) {
switch (mClickedView.getId()) {
case R.id.solid:
Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
b.eraseColor(color);
@ -874,7 +893,10 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if(fos != null) try { fos.close(); } catch(IOException e) {}
if (fos != null) try {
fos.close();
} catch (IOException e) {
}
}
@ -901,13 +923,13 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
private void imagePicked(boolean allow_crop) {
// if(getIntent().getBooleanExtra(INTENT_EXTRA_CROP, false) && allow_crop) {
File file = Utils.getTmpImageFile();
if(allow_crop) {
if(Utils.isSvgFile(file)) {
if (allow_crop) {
if (Utils.isSvgFile(file)) {
allow_crop = false;
}
}
if(allow_crop) {
if (allow_crop) {
ImageCropper.startActivity(this, file, REQUEST_CROP_IMAGE);
} else {
setResult(RESULT_OK);
@ -916,9 +938,9 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
private void setSearchMode(boolean on) {
InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
View src_grp = findViewById(R.id.src_grp);
if(on) {
if (on) {
mSearchText.setVisibility(View.VISIBLE);
mSearchText.setText("");
mSearchText.requestFocus();
@ -947,7 +969,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
ArrayAdapter<?> adapter = (ArrayAdapter<?>) mGridView.getAdapter();
if(adapter != null) {
if (adapter != null) {
adapter.getFilter().filter(s.toString());
}
}
@ -957,6 +979,16 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
private static class BitmapInfo {
Bitmap bitmap;
boolean isNinePatch; // need to be stored because 9patch chunk is lost during resize
private BitmapInfo(Bitmap bitmap, boolean isNinePatch) {
this.bitmap = bitmap;
this.isNinePatch = isNinePatch;
}
}
private static class PkgLabel {
String pkg;
String label;
@ -972,11 +1004,52 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
}
private static class ImageResource {
int res;
String packageName;
String label;
@Override
public String toString() {
return label;
}
}
private static class ImageFile {
File file;
private ImageFile(File file) {
this.file = file;
}
@Override
public String toString() {
return file.getName();
}
}
private static class TextFilter extends Filter {
TextFilter() {
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
}
}
private abstract class MyFilterArrayAdapter<T> extends ArrayAdapter<T> {
private final Object mLock = new Object();
private Filter mFilter;
private List<T> mOriginalItems;
private List<T> mItems;
private final Object mLock = new Object();
public MyFilterArrayAdapter(Context context, int resource) {
@ -1065,9 +1138,6 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
}
private class PkgLabelAdapter extends MyFilterArrayAdapter<PkgLabel> {
public PkgLabelAdapter(Context context, boolean icon) {
@ -1076,20 +1146,20 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
PackageManager pm = getPackageManager();
ArrayList<PkgLabel> items = new ArrayList<PkgLabel>();
if(icon) {
if (icon) {
String myPackagename = getPackageName();
Intent filter = new Intent("org.adw.launcher.icons.ACTION_PICK_ICON");
List<ResolveInfo> ris = pm.queryIntentActivities(filter, 0);
for (ResolveInfo ri : ris) {
String packageName = ri.activityInfo.packageName;
if(!myPackagename.equals(packageName)) {
if (!myPackagename.equals(packageName)) {
PkgLabel pkg = new PkgLabel(packageName, ri.loadLabel(pm).toString());
items.add(pkg);
}
}
} else {
List<PackageInfo> pis = pm.getInstalledPackages(0);
for(PackageInfo pi : pis) {
for (PackageInfo pi : pis) {
PkgLabel pkg = new PkgLabel(pi.packageName, pi.applicationInfo.loadLabel(pm).toString());
items.add(pkg);
}
@ -1100,7 +1170,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
return Utils.sItemNameCollator.compare(pkg1.label, pkg2.label);
}
});
if(!icon) {
if (!icon) {
PkgLabel android_pkg = new PkgLabel(ANDROID, "Android");
items.add(0, android_pkg);
}
@ -1111,42 +1181,30 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(android.R.layout.simple_spinner_item, null);
}
((TextView)convertView.findViewById(android.R.id.text1)).setText(getItem(position).label);
((TextView) convertView.findViewById(android.R.id.text1)).setText(getItem(position).label);
return convertView;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
}
((TextView)convertView.findViewById(android.R.id.text1)).setText(getItem(position).label);
((TextView) convertView.findViewById(android.R.id.text1)).setText(getItem(position).label);
return convertView;
}
}
private static class ImageResource {
int res;
String packageName;
String label;
@Override
public String toString() {
return label;
}
}
private class ImageResourceAdapter extends MyFilterArrayAdapter<ImageResource> {
private boolean mDisplayLabels;
private final boolean mDisplayLabels;
public ImageResourceAdapter(Context context, int resource, List<ImageResource> objects, boolean display_labels) {
super(context, resource);
@ -1158,23 +1216,23 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.item, null);
}
final ImageResource ir = getItem(position);
final TextView title = (TextView) convertView.findViewById(R.id.label);
final ImageView thumbnail = (ImageView) convertView.findViewById(R.id.icon);
final TextView title = convertView.findViewById(R.id.label);
final ImageView thumbnail = convertView.findViewById(R.id.icon);
if(mDisplayLabels) {
if (mDisplayLabels) {
title.setText(ir.label);
title.setVisibility(View.VISIBLE);
} else {
title.setVisibility(View.GONE);
}
BitmapInfo bitmap_info = mThumbnailCache.get(ir.packageName+ir.res);
if(bitmap_info != null) {
BitmapInfo bitmap_info = mThumbnailCache.get(ir.packageName + ir.res);
if (bitmap_info != null) {
Bitmap bitmap = bitmap_info.bitmap;
thumbnail.setImageBitmap(bitmap);
title.setTypeface(null, bitmap_info.isNinePatch ? Typeface.BOLD_ITALIC : Typeface.NORMAL);
@ -1182,7 +1240,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} else {
thumbnail.setTag(ir);
thumbnail.setImageBitmap(null);
new AsyncTask<ImageResource,Void,Bitmap>() {
new AsyncTask<ImageResource, Void, Bitmap>() {
private ImageResource mPackage;
private boolean mIsNinePatch;
@ -1195,36 +1253,36 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
String pkg_name = ir.packageName;
Resources rsrc = pkg_name.equals(ANDROID) ? getResources() : createPackageContext(pkg_name, 0).getResources();
mIsNinePatch = false;
if(Utils.sGetDrawableForDensity!=null) {
if (Utils.sGetDrawableForDensity != null) {
try {
BitmapDrawable d=(BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity);
BitmapDrawable d = (BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity);
Bitmap orig_bmp = d.getBitmap();
mIsNinePatch = NinePatch.isNinePatchChunk(orig_bmp.getNinePatchChunk());
bmp = Utils.createStandardSizedIcon(orig_bmp, mStandardIconSize);
} catch(Throwable e) {
} catch (Throwable e) {
// pass, continue with classic method
}
}
if(bmp == null) {
if (bmp == null) {
bmp = BitmapFactory.decodeResource(rsrc, id);
if(bmp != null) {
if (bmp != null) {
mIsNinePatch = NinePatch.isNinePatchChunk(bmp.getNinePatchChunk());
}
}
} catch (Throwable e) {
e.printStackTrace();
}
if(bmp == null) {
if (bmp == null) {
bmp = mDefaultIcon;
}
mThumbnailCache.put(ir.packageName+ir.res, new BitmapInfo(bmp, mIsNinePatch));
mThumbnailCache.put(ir.packageName + ir.res, new BitmapInfo(bmp, mIsNinePatch));
return bmp;
}
@Override
protected void onPostExecute(Bitmap bmp) {
if(thumbnail.getTag() == mPackage) {
if (thumbnail.getTag() == mPackage) {
thumbnail.setImageBitmap(bmp);
title.setTypeface(null, mIsNinePatch ? Typeface.BOLD_ITALIC : Typeface.NORMAL);
}
@ -1236,30 +1294,17 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
}
}
private static class ImageFile {
File file;
private ImageFile(File file) {
this.file = file;
}
@Override
public String toString() {
return file.getName();
}
}
private class ImageFileAdapter extends MyFilterArrayAdapter<ImageFile> {
private boolean mDisplayLabels;
private Bitmap mFolderIcon;
private final boolean mDisplayLabels;
private final Bitmap mFolderIcon;
public ImageFileAdapter(Context context, int resource, List<ImageFile> objects, boolean display_labels) {
super(context, resource);
mDisplayLabels = display_labels;
int[] textSizeAttr = new int[] { android.R.attr.colorForeground };
int[] textSizeAttr = new int[]{android.R.attr.colorForeground};
TypedArray a = context.obtainStyledAttributes(textSizeAttr);
mFolderIcon = Utils.createIconFromText(Utils.getStandardIconSize(), "f", a.getColor(0, 0));
@ -1268,22 +1313,22 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.item, null);
}
final ImageFile imf = getItem(position);
final TextView title = (TextView) convertView.findViewById(R.id.label);
final ImageView thumbnail = (ImageView) convertView.findViewById(R.id.icon);
final TextView title = convertView.findViewById(R.id.label);
final ImageView thumbnail = convertView.findViewById(R.id.icon);
if(mDisplayLabels) {
if (mDisplayLabels) {
title.setText(imf.file.getName());
title.setVisibility(View.VISIBLE);
} else {
title.setVisibility(View.GONE);
}
if(imf.file.isDirectory()) {
if (imf.file.isDirectory()) {
thumbnail.setImageBitmap(mFolderIcon);
} else {
BitmapInfo bitmap_info = mThumbnailCache.get(imf.file.getAbsolutePath());
@ -1335,21 +1380,4 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
// return mDisplayLabels;
// }
}
private static class TextFilter extends Filter {
TextFilter() {
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
}
}
}

View file

@ -32,12 +32,12 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
@ -56,8 +56,8 @@ import java.util.List;
import java.util.Stack;
public class LockScreen extends Dashboard {
private static final int DIALOG_UNLOCK = 1;
private static final int DIALOG_UNLOCK = 1;
public static LockScreen sThis;
public static Integer sMyTaskId;
@ -77,10 +77,10 @@ public class LockScreen extends Dashboard {
mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(2);
int size = tasks.size();
if(size > 0) {
if (size > 0) {
sMyTaskId = tasks.get(0).id;
}
if(size == 2) {
if (size == 2) {
mLastTaskId = tasks.get(1).id;
} else {
mLastTaskId = null;
@ -113,19 +113,16 @@ public class LockScreen extends Dashboard {
}
try {
Method getActionBar=getClass().getMethod("getActionBar");
Object action_bar=getActionBar.invoke(this, (Object[])null);
action_bar.getClass().getMethod("hide").invoke(action_bar, (Object[])null);
} catch(Exception e) {
Method getActionBar = getClass().getMethod("getActionBar");
Object action_bar = getActionBar.invoke(this, (Object[]) null);
action_bar.getClass().getMethod("hide").invoke(action_bar, (Object[]) null);
} catch (Exception e) {
// pass, API level 11
}
mNavigationStack=new Stack<Integer>();
mNavigationStack = new Stack<Integer>();
LLApp llApp = LLApp.get();
LightningEngine engine = llApp.getAppEngine();
@ -133,13 +130,13 @@ public class LockScreen extends Dashboard {
int lockScreen = globalConfig.lockScreen;
mLockScreenPage = engine.getOrLoadPage(lockScreen);
mItemLayout=(ItemLayout)findViewById(R.id.drawer_il);
mItemLayout = findViewById(R.id.drawer_il);
mScreen.takeItemLayoutOwnership(mItemLayout);
mItemLayout.setHonourFocusChange(false);
mItemLayout.setPage(mLockScreenPage);
configureActivity(mLockScreenPage);
if(globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) {
if (globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) {
stopService(llApp.getWindowServiceIntent());
}
@ -159,7 +156,7 @@ public class LockScreen extends Dashboard {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mScreen.zoomToOrigin(mScreen.getTargetOrTopmostItemLayout());
return true;
}
@ -197,9 +194,12 @@ public class LockScreen extends Dashboard {
@Override
public void onShow(DialogInterface dialogInterface) {
finish();
try { removeDialog(DIALOG_UNLOCK); } catch(Exception e) {}
if(mRestorePreviousTask) {
if(mLastTaskId != null) {
try {
removeDialog(DIALOG_UNLOCK);
} catch (Exception e) {
}
if (mRestorePreviousTask) {
if (mLastTaskId != null) {
try {
mMoveTaskToFront.invoke(mActivityManager, mLastTaskId, 0);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
@ -207,7 +207,7 @@ public class LockScreen extends Dashboard {
e.printStackTrace();
}
} else {
if(mNeedDashboardRestart) {
if (mNeedDashboardRestart) {
Intent intent = new Intent(LockScreen.this, Dashboard.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
@ -220,15 +220,17 @@ public class LockScreen extends Dashboard {
}
public void unlock(boolean restore_previous_task) {
mRestorePreviousTask = restore_previous_task;
try { showDialog(DIALOG_UNLOCK); } catch(Exception e) {}
try {
showDialog(DIALOG_UNLOCK);
} catch (Exception e) {
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
LLApp llApp = LLApp.get();
GlobalConfig globalConfig = llApp.getAppEngine().getGlobalConfig();
if(globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) {
if (globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) {
startService(llApp.getWindowServiceIntent());
}
Intent unlocked = new Intent(Dashboard.BROADCAST_ACTION_UNLOCKED);
@ -250,7 +252,7 @@ public class LockScreen extends Dashboard {
@Override
public void onWidgetClicked() {
if(mGlobalConfig.launchUnlock) {
if (mGlobalConfig.launchUnlock) {
mItemLayout.postDelayed(new Runnable() {
@Override
public void run() {
@ -262,7 +264,7 @@ public class LockScreen extends Dashboard {
@Override
public ItemLayout loadRootItemLayout(int page, boolean reset_navigation_history, boolean displayImmediately, boolean animate) {
if(mItemLayout.getPage().id == page) {
if (mItemLayout.getPage().id == page) {
return mItemLayout;
} else {
return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate);
@ -297,7 +299,7 @@ public class LockScreen extends Dashboard {
@Override
protected void launchIntent(Intent intent, ItemView itemView) {
super.launchIntent(intent, itemView);
if(mGlobalConfig.launchUnlock) {
if (mGlobalConfig.launchUnlock) {
unlock(false);
}
}

View file

@ -47,14 +47,48 @@ import net.pierrox.lightning_launcher.util.SetVariableDialog;
import net.pierrox.lightning_launcher_extreme.R;
public class Shortcuts extends ResourceWrapperListActivity {
private static final String INDENT = " ";
private static final String INDENT = " ";
private String[] mItems;
private boolean mIsForTaskerScript;
private boolean mIsForTaskerVariable;
private String[] mItems;
private boolean mIsForTaskerScript;
private boolean mIsForTaskerVariable;
public static Intent getShortcutForIntent(Activity activity, String name, Intent intent) {
if (forTasker(activity)) {
Intent result = new Intent();
Bundle bundle = new Bundle();
bundle.putString("i", intent.toUri(0));
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE, bundle);
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_STRING_BLURB, name);
return result;
} else {
int p;
String path = intent.getStringExtra(Customize.INTENT_EXTRA_PAGE_PATH);
if (path == null) {
p = intent.getIntExtra(Customize.INTENT_EXTRA_PAGE_ID, Page.FIRST_DASHBOARD_PAGE);
} else {
p = new ContainerPath(path).getLast();
}
int icon = p == Page.APP_DRAWER_PAGE ? R.drawable.all_apps : R.drawable.icon;
Parcelable icon_resource = Intent.ShortcutIconResource.fromContext(activity, icon);
Intent shortcut = new Intent();
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon_resource);
return shortcut;
}
}
private static boolean forTasker(Activity activity) {
final String action = activity.getIntent().getAction();
return action != null && action.equals(com.twofortyfouram.locale.Intent.ACTION_EDIT_SETTING);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState) {
final Intent intent = getIntent();
String className = intent.getComponent().getClassName();
mIsForTaskerScript = className.endsWith("TS");
@ -62,14 +96,12 @@ public class Shortcuts extends ResourceWrapperListActivity {
Utils.setTheme(this, mIsForTaskerScript ? Utils.APP_THEME_TRANSLUCENT : Utils.APP_THEME);
super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
if(mIsForTaskerScript) {
if (mIsForTaskerScript) {
pickScriptAndCreateShortcut();
return;
} else if(mIsForTaskerVariable) {
} else if (mIsForTaskerVariable) {
pickVariableAndCreateShortcut();
return;
} else {
mItems = new String[]{
getString(R.string.settings), // 0
@ -110,11 +142,11 @@ public class Shortcuts extends ResourceWrapperListActivity {
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent;
String name;
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent;
String name;
if (position == 29) {
intent = new Intent(this, ScreenManager.class);
intent.setAction(Intent.ACTION_EDIT);
@ -195,38 +227,9 @@ public class Shortcuts extends ResourceWrapperListActivity {
} else if (position >= 17 && position < 29) {
intent.putExtra(Customize.INTENT_EXTRA_PAGE_ID, new ContainerPath(Page.APP_DRAWER_PAGE).toString());
}
}
createShortcutForIntent(name, intent);
}
public static Intent getShortcutForIntent(Activity activity, String name, Intent intent) {
if(forTasker(activity)) {
Intent result = new Intent();
Bundle bundle = new Bundle();
bundle.putString("i", intent.toUri(0));
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE, bundle);
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_STRING_BLURB, name);
return result;
} else {
int p;
String path = intent.getStringExtra(Customize.INTENT_EXTRA_PAGE_PATH);
if(path == null) {
p = intent.getIntExtra(Customize.INTENT_EXTRA_PAGE_ID, Page.FIRST_DASHBOARD_PAGE);
} else {
p = new ContainerPath(path).getLast();
}
int icon = p == Page.APP_DRAWER_PAGE ? R.drawable.all_apps : R.drawable.icon;
Parcelable icon_resource = Intent.ShortcutIconResource.fromContext(activity, icon);
Intent shortcut = new Intent();
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon_resource);
return shortcut;
}
createShortcutForIntent(name, intent);
}
private void createShortcutForIntent(String name, Intent intent) {
@ -239,7 +242,7 @@ public class Shortcuts extends ResourceWrapperListActivity {
Script script = LLApp.get().getAppEngine().getScriptManager().getOrLoadScript(id);
String extra_data = Script.encodeIdAndData(id, data);
if(forTasker(this)) {
if (forTasker(this)) {
// for scripts triggered by Tasker, pass the data as a string extra otherwise '%' is escaped in Intent.toUri
Intent result = new Intent();
@ -252,16 +255,16 @@ public class Shortcuts extends ResourceWrapperListActivity {
}
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE, bundle);
String data_e;
if(data == null) {
if (data == null) {
data_e = "";
} else {
if(data.length()>30) {
data_e = data.substring(0, 30)+"";
if (data.length() > 30) {
data_e = data.substring(0, 30) + "";
} else {
data_e = data;
}
}
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_STRING_BLURB, script.name+data_e);
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_STRING_BLURB, script.name + data_e);
setResult(RESULT_OK, result);
} else {
Intent intent = new Intent(Shortcuts.this, Dashboard.class);
@ -282,14 +285,14 @@ public class Shortcuts extends ResourceWrapperListActivity {
public void onScriptPicked(String id_data, int target) {
final Pair<Integer, String> pair = Script.decodeIdAndData(id_data);
createScriptShortcut(pair.first, pair.second, target);
if(mIsForTaskerScript) {
if (mIsForTaskerScript) {
finish();
}
}
@Override
public void onScriptPickerCanceled() {
if(mIsForTaskerScript) {
if (mIsForTaskerScript) {
finish();
}
}
@ -307,7 +310,7 @@ public class Shortcuts extends ResourceWrapperListActivity {
Bundle bundle = new Bundle();
bundle.putInt(LightningIntent.INTENT_EXTRA_ACTION, GlobalConfig.SET_VARIABLE);
bundle.putString(LightningIntent.INTENT_EXTRA_DATA, variable.encode());
bundle.putString(LightningIntent.INTENT_EXTRA_DATA, variable.encode());
if (TaskerPlugin.Setting.hostSupportsOnFireVariableReplacement(Shortcuts.this)) {
TaskerPlugin.Setting.setVariableReplaceKeys(bundle, new String[]{LightningIntent.INTENT_EXTRA_DATA});
}
@ -324,9 +327,4 @@ public class Shortcuts extends ResourceWrapperListActivity {
}
}).show();
}
private static boolean forTasker(Activity activity) {
final String action = activity.getIntent().getAction();
return action != null && action.equals(com.twofortyfouram.locale.Intent.ACTION_EDIT_SETTING);
}
}

View file

@ -37,7 +37,7 @@ public final class ActionsDescription {
private static final Action[] sAllActions = new Action[]{
new Action(GlobalConfig.NOTHING, R.string.an_n, Action.CAT_NONE, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_TYPE_SCRIPT, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_l, Action.CAT_LAUNCH_AND_APPS, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_l, Action.CAT_LAUNCH_AND_APPS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.LAUNCH_APP, R.string.an_la, Action.CAT_LAUNCH_AND_APPS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.LAUNCH_SHORTCUT, R.string.an_ls, Action.CAT_LAUNCH_AND_APPS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.LAUNCH_ITEM, R.string.an_i_l, Action.CAT_LAUNCH_AND_APPS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_ITEM, Build.VERSION_CODES.FROYO),
@ -47,7 +47,7 @@ public final class ActionsDescription {
new Action(GlobalConfig.RESTART, R.string.an_re, Action.CAT_LAUNCH_AND_APPS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_n, Action.CAT_NAVIGATION, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_n, Action.CAT_NAVIGATION, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.GO_HOME, R.string.an_gh, Action.CAT_NAVIGATION, Action.FLAG_TYPE_DESKTOP, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.GO_HOME_ZOOM_TO_ORIGIN, R.string.an_ghz100, Action.CAT_NAVIGATION, Action.FLAG_TYPE_DESKTOP, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.GO_DESKTOP_POSITION, R.string.an_gdp, Action.CAT_NAVIGATION, Action.FLAG_TYPE_DESKTOP, Build.VERSION_CODES.FROYO),
@ -60,7 +60,7 @@ public final class ActionsDescription {
new Action(GlobalConfig.BACK, R.string.an_b, Action.CAT_NAVIGATION, Action.FLAG_TYPE_DESKTOP, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_m, Action.CAT_MENU_STATUS_BAR, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_m, Action.CAT_MENU_STATUS_BAR, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.LAUNCHER_MENU, R.string.an_lm, Action.CAT_MENU_STATUS_BAR, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.ITEM_MENU, R.string.an_i_me, Action.CAT_MENU_STATUS_BAR, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_ITEM, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CUSTOM_MENU, R.string.an_cm, Action.CAT_MENU_STATUS_BAR, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
@ -70,13 +70,13 @@ public final class ActionsDescription {
new Action(GlobalConfig.SHOW_NOTIFICATIONS, R.string.an_sn, Action.CAT_MENU_STATUS_BAR, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_f, Action.CAT_FOLDERS, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_f, Action.CAT_FOLDERS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.OPEN_FOLDER, R.string.an_of, Action.CAT_FOLDERS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CLOSE_TOPMOST_FOLDER, R.string.an_ctf, Action.CAT_FOLDERS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CLOSE_ALL_FOLDERS, R.string.an_caf, Action.CAT_FOLDERS, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_ed, Action.CAT_EDITION, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_ed, Action.CAT_EDITION, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.EDIT_LAYOUT, R.string.an_el, Action.CAT_EDITION, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.ADD_ITEM, R.string.an_ao, Action.CAT_EDITION, Action.FLAG_TYPE_DESKTOP, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.MOVE_ITEM, R.string.an_i_m, Action.CAT_EDITION, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_ITEM, Build.VERSION_CODES.FROYO),
@ -86,7 +86,7 @@ public final class ActionsDescription {
new Action(GlobalConfig.OPEN_HIERARCHY_SCREEN, R.string.an_ohs, Action.CAT_EDITION, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_ex, Action.CAT_EXTERNAL, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_ex, Action.CAT_EXTERNAL, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.SELECT_WALLPAPER, R.string.an_sw, Action.CAT_EXTERNAL, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.WALLPAPER_TAP, R.string.an_wt, Action.CAT_EXTERNAL, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.WALLPAPER_SECONDARY_TAP, R.string.an_wst, Action.CAT_EXTERNAL, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
@ -96,16 +96,16 @@ public final class ActionsDescription {
new Action(GlobalConfig.HIDE_FLOATING_DESKTOP, R.string.an_ho, Action.CAT_EXTERNAL, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_a, Action.CAT_ADVANCED, Action.FLAG_TYPE_DESKTOP |Action.FLAG_TYPE_APP_DRAWER |Action.FLAG_TYPE_SCRIPT, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.CATEGORY, R.string.acd_a, Action.CAT_ADVANCED, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_TYPE_SCRIPT, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.RUN_SCRIPT, R.string.an_rs, Action.CAT_ADVANCED, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_TYPE_SCRIPT, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.SET_VARIABLE, R.string.an_sv, Action.CAT_ADVANCED, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER, Build.VERSION_CODES.FROYO),
new Action(GlobalConfig.UNSET, R.string.an_u, Action.CAT_ADVANCED, Action.FLAG_TYPE_DESKTOP | Action.FLAG_TYPE_APP_DRAWER | Action.FLAG_TYPE_SCRIPT, Build.VERSION_CODES.FROYO),
};
private ArrayList<Action> mActions;
private String mActionNames[];
private int mType;
private boolean mForItem;
private final ArrayList<Action> mActions;
private final String[] mActionNames;
private final int mType;
private final boolean mForItem;
public ActionsDescription(Context context, int type, boolean forItem) {
mActions = new ArrayList<>(sAllActions.length);
@ -113,7 +113,7 @@ public final class ActionsDescription {
mForItem = forItem;
for (Action action : sAllActions) {
boolean isItem = (action.flags & Action.FLAG_ITEM) == Action.FLAG_ITEM;
if (((action.flags&type) == type) && (forItem || !isItem) && Build.VERSION.SDK_INT >= action.minSdkVersion) {
if (((action.flags & type) == type) && (forItem || !isItem) && Build.VERSION.SDK_INT >= action.minSdkVersion) {
mActions.add(action);
}
}
@ -144,18 +144,18 @@ public final class ActionsDescription {
}
}
return 0;
}
}
public String getActionName(int action) {
return mActionNames[getActionIndex(action)];
}
public int getActionAt(int index) {
return mActions.get(index).action;
}
public int getActionAt(int index) {
return mActions.get(index).action;
}
public String[] getActionNames() {
return mActionNames;
}
public String[] getActionNames() {
return mActionNames;
}
}

View file

@ -28,7 +28,6 @@ import net.pierrox.lightning_launcher.activities.Dashboard;
import net.pierrox.lightning_launcher.configuration.FolderConfig;
import net.pierrox.lightning_launcher.configuration.ItemConfig;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.views.item.ItemView;
import org.json.JSONException;
@ -40,10 +39,176 @@ import java.util.ArrayList;
import java.util.LinkedList;
public class UndoStack {
private final Dashboard mDashboard;
private final File mTempStorageDirectory;
private final int mMaxSize;
private final LinkedList<Operation> mUndoOperations = new LinkedList<>();
private final LinkedList<Operation> mRedoOperations = new LinkedList<>();
private final LinkedList<SelectionState> mRedoSelectionState = new LinkedList<>();
private UndoListener mListener;
public UndoStack(Dashboard dashboard, File tempStorageDirectory, int maxSize) {
mDashboard = dashboard;
mTempStorageDirectory = tempStorageDirectory;
mMaxSize = maxSize;
if (mTempStorageDirectory.exists()) {
Utils.deleteDirectory(mTempStorageDirectory, false);
}
}
public void clear() {
if (mUndoOperations.size() > 0 || mRedoOperations.size() > 0) {
Utils.deleteDirectory(mTempStorageDirectory, false);
mUndoOperations.clear();
mRedoOperations.clear();
notifyUndoListener();
}
}
public void setUndoListener(UndoListener listener) {
mListener = listener;
}
public boolean canUndo() {
return mUndoOperations.size() > 0;
}
public boolean canRedo() {
return mRedoOperations.size() > 0;
}
private Operation getNextUndoOperation() {
return mUndoOperations.isEmpty() ? null : mUndoOperations.getLast();
}
public void undo() {
mRedoSelectionState.add(mDashboard.getSelectionState());
Operation operation = mUndoOperations.removeLast();
mRedoOperations.add(operation);
operation.undo();
notifyUndoListener();
}
public boolean willDeleteWidget(boolean for_undo) {
Operation operation = for_undo ? mUndoOperations.getLast() : mRedoOperations.getLast();
if (operation instanceof PageOperationAddOrRemoveItem) {
PageOperationAddOrRemoveItem addOrRemoveItem = (PageOperationAddOrRemoveItem) operation;
Item item = addOrRemoveItem.mPage.findItemById(addOrRemoveItem.mItemId);
boolean widget = item instanceof Widget || (item instanceof Folder && ((Folder) item).hasWidget());
if (for_undo && addOrRemoveItem.mForAdd && widget) return true;
return !for_undo && !addOrRemoveItem.mForAdd && widget;
}
return false;
}
private Operation getNextRedoOperation() {
return mRedoOperations.getLast();
}
public void redo() {
Operation operation = mRedoOperations.removeLast();
mUndoOperations.add(operation);
operation.redo();
notifyUndoListener();
mDashboard.setSelectionState(mRedoSelectionState.removeLast());
}
public void storeGroupStart() {
storeGroupStart(null);
}
public void storeGroupStart(SelectionState selectionState) {
addOperation(new GroupStartOperation(selectionState));
}
public void storeGroupEnd() {
int l = mUndoOperations.size();
if (mUndoOperations.get(l - 1).getClass() == GroupStartOperation.class) {
// nothing between start and end: remove the start and don't add a end
mUndoOperations.removeLast();
} else if (mUndoOperations.get(l - 2).getClass() == GroupStartOperation.class) {
// a single operation between start and end: remove the start and don't add a end
mUndoOperations.remove(l - 2);
} else {
addOperation(new GroupEndOperation());
}
}
public void storeItemSetCell(ItemView itemView, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationSetGeometry(itemView, oldGeometry));
}
public void storeItemSetTransform(ItemView itemView, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationSetGeometry(itemView, oldGeometry));
}
public void storeItemSetViewSize(ItemView itemView, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationSetGeometry(itemView, oldGeometry));
}
public void storeItemGridAttachment(ItemView itemView, boolean wasAttached, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationGridAttachment(itemView, wasAttached, oldGeometry));
}
public void storeItemPinMode(ItemView itemView, ItemConfig.PinMode oldPinMode, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationPinMode(itemView, oldPinMode, oldGeometry));
}
public void storePageAddItem(Item item) {
addOperation(new PageOperationAddOrRemoveItem(item, true));
}
public void storePageRemoveItem(Item item) {
addOperation(new PageOperationAddOrRemoveItem(item, false));
}
public void storePageItemZOrder(Page page, Item item, int oldZOrder) {
addOperation(new PageOperationItemZOrder(page, item, oldZOrder));
}
public void storePageItemMove(ItemView newItemView, int oldItemId, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationMove(newItemView, oldItemId, oldGeometry));
}
public void storeItemState(Item item) {
addOperation(new ItemOperationState(item));
}
public void storePageState(Page page) {
addOperation(new PageOperationState(page));
}
private void addOperation(Operation operation) {
for (Operation op : mRedoOperations) {
op.clearTempStorage();
}
mRedoOperations.clear();
if (mUndoOperations.size() == mMaxSize) {
Operation op = mUndoOperations.removeFirst();
op.clearTempStorage();
}
mUndoOperations.add(operation);
notifyUndoListener();
}
private void notifyUndoListener() {
mListener.onUndoStackStateChanged(canUndo(), canRedo());
}
public interface UndoListener {
public void onUndoStackStateChanged(boolean can_undo, boolean can_redo);
public void onUndoStackItemChanged(Item item);
public void onUndoStackPageChanged(Page page);
void onUndoStackStateChanged(boolean can_undo, boolean can_redo);
void onUndoStackItemChanged(Item item);
void onUndoStackPageChanged(Page page);
}
private abstract class Operation {
@ -64,7 +229,7 @@ public class UndoStack {
protected File getTempStorageDirectory() {
File dir = new File(mTempStorageDirectory, String.valueOf(hashCode()));
if(!dir.exists()) {
if (!dir.exists()) {
//noinspection ResultOfMethodCallIgnored
dir.mkdirs();
}
@ -94,7 +259,7 @@ public class UndoStack {
private class GroupStartOperation extends Operation {
protected GroupStartOperation(SelectionState selectionState) {
if(selectionState != null) {
if (selectionState != null) {
mSelectionState = selectionState;
}
}
@ -110,7 +275,7 @@ public class UndoStack {
do {
op = UndoStack.this.getNextRedoOperation();
UndoStack.this.redo();
} while(op.getClass() != GroupEndOperation.class);
} while (op.getClass() != GroupEndOperation.class);
super.redo();
}
@ -129,10 +294,10 @@ public class UndoStack {
do {
op = UndoStack.this.getNextUndoOperation();
// check for null because if the stack is full, older operations may have been removed, including balanced GroupStartOperation
if(op != null) {
if (op != null) {
UndoStack.this.undo();
}
} while(op != null && op.getClass() != GroupStartOperation.class);
} while (op != null && op.getClass() != GroupStartOperation.class);
}
@Override
@ -160,8 +325,8 @@ public class UndoStack {
}
private class PageOperationItemZOrder extends PageOperation {
private int mOldZOrder;
private int mNewZOrder;
private final int mOldZOrder;
private final int mNewZOrder;
protected PageOperationItemZOrder(Page page, Item item, int oldZOrder) {
super(page);
@ -190,8 +355,8 @@ public class UndoStack {
}
private class PageOperationAddOrRemoveItem extends PageOperation {
private int mItemId;
private boolean mForAdd;
private final int mItemId;
private final boolean mForAdd;
private JSONObject mJsonItem;
private int mZOrder;
@ -201,7 +366,7 @@ public class UndoStack {
mItemId = item.mId;
mForAdd = forAdd;
if(!mForAdd) {
if (!mForAdd) {
saveItemState(item);
} else {
mZOrder = mPage.items.size();
@ -211,7 +376,7 @@ public class UndoStack {
@Override
protected void undo() {
if(mForAdd) {
if (mForAdd) {
doRemove();
notifyPageChanged();
} else {
@ -223,7 +388,7 @@ public class UndoStack {
@Override
protected void redo() {
if(mForAdd) {
if (mForAdd) {
doAdd();
mListener.onUndoStackPageChanged(mPage);
} else {
@ -239,13 +404,15 @@ public class UndoStack {
private void saveItemState(Item item) {
exchangeFilesWithUndo(item, true);
try { mJsonItem = item.toJSONObject(); } catch (JSONException e) { /*pass*/ }
try {
mJsonItem = item.toJSONObject();
} catch (JSONException e) { /*pass*/ }
mZOrder = mPage.items.indexOf(item);
}
private void doRemove() {
Item item = mPage.findItemById(mItemId);
if(mForAdd) {
if (mForAdd) {
saveItemState(item);
}
mPage.removeItem(item, false);
@ -268,7 +435,7 @@ public class UndoStack {
}
/**
* param direction true: copy to undo, false retrieve from undo
* param direction true: copy to undo, false retrieve from undo
*/
private void exchangeFilesWithUndo(Item item, boolean direction) {
byte[] buffer = new byte[4096];
@ -276,9 +443,9 @@ public class UndoStack {
ArrayList<File> icons = new ArrayList<>();
item.getIconFiles(mPage.getIconDir(), icons);
int index = 0;
for(File from : icons) {
for (File from : icons) {
File to = new File(out, String.valueOf(index));
if(direction) {
if (direction) {
Utils.copyFileSafe(buffer, from, to);
} else {
Utils.copyFileSafe(buffer, to, from);
@ -286,8 +453,8 @@ public class UndoStack {
index++;
}
if(item instanceof Folder) {
Folder f = (Folder)item;
if (item instanceof Folder) {
Folder f = (Folder) item;
Page page = f.getOrLoadFolderPage();
exchangePageFilesWithUndo(page, direction, buffer, new ArrayList<Integer>());
}
@ -296,9 +463,9 @@ public class UndoStack {
private void exchangePageFilesWithUndo(Page page, boolean direction, byte[] buffer, ArrayList<Integer> done) {
try {
File folder_dir = page.getPageDir();
File temp_dir = new File(getTempStorageDirectory(), "page_"+page.id);
if(direction) {
if(page.isModified()) page.save();
File temp_dir = new File(getTempStorageDirectory(), "page_" + page.id);
if (direction) {
if (page.isModified()) page.save();
Utils.copyDirectory(buffer, folder_dir, temp_dir);
} else {
Utils.copyDirectory(buffer, temp_dir, folder_dir);
@ -308,11 +475,11 @@ public class UndoStack {
e.printStackTrace();
}
for(Item item : page.items) {
if(item instanceof Folder) {
Folder f = (Folder)item;
for (Item item : page.items) {
if (item instanceof Folder) {
Folder f = (Folder) item;
int pageId = f.getFolderPageId();
if(!done.contains(pageId)) {
if (!done.contains(pageId)) {
// prevent endless recursion when the folder is in itself
done.add(pageId);
exchangePageFilesWithUndo(f.getOrLoadFolderPage(), direction, buffer, done);
@ -351,7 +518,7 @@ public class UndoStack {
exchangeFilesWithUndo(!direction, true);
exchangeFilesWithUndo(direction, false);
mPage.reload();
if(previous_style != mPage.config.defaultFolderConfig.iconStyle) {
if (previous_style != mPage.config.defaultFolderConfig.iconStyle) {
Utils.updateFolderIconStyle(mPage);
}
mListener.onUndoStackPageChanged(mPage);
@ -389,6 +556,7 @@ public class UndoStack {
private abstract class ItemOperation extends Operation {
protected int itemId;
public ItemOperation(Item item) {
this.itemId = item.getId();
}
@ -442,7 +610,8 @@ public class UndoStack {
}
private class ItemOperationGridAttachment extends ItemOperationSetGeometry {
private boolean wasAttached;
private final boolean wasAttached;
private ItemOperationGridAttachment(ItemView itemView, boolean wasAttached, SavedItemGeometry oldGeometry) {
super(itemView, oldGeometry);
this.wasAttached = wasAttached;
@ -466,8 +635,9 @@ public class UndoStack {
}
private class ItemOperationPinMode extends ItemOperationSetGeometry {
private ItemConfig.PinMode oldPinMode;
private ItemConfig.PinMode newPinMode;
private final ItemConfig.PinMode oldPinMode;
private final ItemConfig.PinMode newPinMode;
private ItemOperationPinMode(ItemView itemView, ItemConfig.PinMode oldPinMode, SavedItemGeometry oldGeometry) {
super(itemView, oldGeometry);
this.oldPinMode = oldPinMode;
@ -492,10 +662,10 @@ public class UndoStack {
}
private class ItemOperationMove extends ItemOperationSetGeometry {
private int mOldItemId;
private int mNewItemId;
private int mOldPage;
private int mNewPage;
private final int mOldItemId;
private final int mNewItemId;
private final int mOldPage;
private final int mNewPage;
private ItemOperationMove(ItemView itemView, int oldItemId, SavedItemGeometry oldGeometry) {
super(itemView, oldGeometry);
@ -546,7 +716,9 @@ public class UndoStack {
public ItemOperationState(Item item) {
super(item);
try { mOldJsonItem = item.toJSONObject(); } catch (JSONException e) { /*pass*/ }
try {
mOldJsonItem = item.toJSONObject();
} catch (JSONException e) { /*pass*/ }
ArrayList<File> icons = new ArrayList<>();
Page page = item.getPage();
@ -563,7 +735,9 @@ public class UndoStack {
exchangeFilesWithUndo(icons, false, true); // save new files to temp
try { mNewJsonItem = new_item.toJSONObject(); } catch (JSONException e) { /*pass*/ }
try {
mNewJsonItem = new_item.toJSONObject();
} catch (JSONException e) { /*pass*/ }
try {
int zorder = page.items.indexOf(new_item);
@ -610,17 +784,17 @@ public class UndoStack {
private void exchangeFilesWithUndo(ArrayList<File> icons, boolean old, boolean direction) {
byte[] buffer = new byte[4096];
File out = new File(getTempStorageDirectory(), old?"o":"n");
File out = new File(getTempStorageDirectory(), old ? "o" : "n");
out.mkdir();
int index = 0;
for(File from : icons) {
for (File from : icons) {
File to = new File(out, String.valueOf(index));
if(!direction) {
if (!direction) {
File tmp = to;
to = from;
from = tmp;
}
if(from.exists()) {
if (from.exists()) {
Utils.copyFileSafe(buffer, from, to);
} else {
to.delete();
@ -629,168 +803,4 @@ public class UndoStack {
}
}
}
private Dashboard mDashboard;
private File mTempStorageDirectory;
private int mMaxSize;
private LinkedList<Operation> mUndoOperations = new LinkedList<>();
private LinkedList<Operation> mRedoOperations = new LinkedList<>();
private LinkedList<SelectionState> mRedoSelectionState = new LinkedList<>();
private UndoListener mListener;
public UndoStack(Dashboard dashboard, File tempStorageDirectory, int maxSize) {
mDashboard = dashboard;
mTempStorageDirectory = tempStorageDirectory;
mMaxSize = maxSize;
if(mTempStorageDirectory.exists()) {
Utils.deleteDirectory(mTempStorageDirectory, false);
}
}
public void clear() {
if(mUndoOperations.size()>0 || mRedoOperations.size()>0) {
Utils.deleteDirectory(mTempStorageDirectory, false);
mUndoOperations.clear();
mRedoOperations.clear();
notifyUndoListener();
}
}
public void setUndoListener(UndoListener listener) {
mListener = listener;
}
public boolean canUndo() {
return mUndoOperations.size() > 0;
}
public boolean canRedo() {
return mRedoOperations.size() > 0;
}
private Operation getNextUndoOperation() {
return mUndoOperations.isEmpty() ? null : mUndoOperations.getLast();
}
public void undo() {
mRedoSelectionState.add(mDashboard.getSelectionState());
Operation operation = mUndoOperations.removeLast();
mRedoOperations.add(operation);
operation.undo();
notifyUndoListener();
}
public boolean willDeleteWidget(boolean for_undo) {
Operation operation = for_undo ? mUndoOperations.getLast() : mRedoOperations.getLast();
if(operation instanceof PageOperationAddOrRemoveItem) {
PageOperationAddOrRemoveItem addOrRemoveItem = (PageOperationAddOrRemoveItem) operation;
Item item = addOrRemoveItem.mPage.findItemById(addOrRemoveItem.mItemId);
boolean widget = item instanceof Widget || (item instanceof Folder && ((Folder)item).hasWidget());
if(for_undo && addOrRemoveItem.mForAdd && widget) return true;
if(!for_undo && !addOrRemoveItem.mForAdd && widget) return true;
}
return false;
}
private Operation getNextRedoOperation() {
return mRedoOperations.getLast();
}
public void redo() {
Operation operation = mRedoOperations.removeLast();
mUndoOperations.add(operation);
operation.redo();
notifyUndoListener();
mDashboard.setSelectionState(mRedoSelectionState.removeLast());
}
public void storeGroupStart() {
storeGroupStart(null);
}
public void storeGroupStart(SelectionState selectionState) {
addOperation(new GroupStartOperation(selectionState));
}
public void storeGroupEnd() {
int l = mUndoOperations.size();
if(mUndoOperations.get(l-1).getClass() == GroupStartOperation.class) {
// nothing between start and end: remove the start and don't add a end
mUndoOperations.removeLast();
} else if(mUndoOperations.get(l-2).getClass() == GroupStartOperation.class) {
// a single operation between start and end: remove the start and don't add a end
mUndoOperations.remove(l-2);
} else {
addOperation(new GroupEndOperation());
}
}
public void storeItemSetCell(ItemView itemView, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationSetGeometry(itemView, oldGeometry));
}
public void storeItemSetTransform(ItemView itemView, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationSetGeometry(itemView, oldGeometry));
}
public void storeItemSetViewSize(ItemView itemView, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationSetGeometry(itemView, oldGeometry));
}
public void storeItemGridAttachment(ItemView itemView, boolean wasAttached, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationGridAttachment(itemView, wasAttached, oldGeometry));
}
public void storeItemPinMode(ItemView itemView, ItemConfig.PinMode oldPinMode, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationPinMode(itemView, oldPinMode, oldGeometry));
}
public void storePageAddItem(Item item) {
addOperation(new PageOperationAddOrRemoveItem(item, true));
}
public void storePageRemoveItem(Item item) {
addOperation(new PageOperationAddOrRemoveItem(item, false));
}
public void storePageItemZOrder(Page page, Item item, int oldZOrder) {
addOperation(new PageOperationItemZOrder(page, item, oldZOrder));
}
public void storePageItemMove(ItemView newItemView, int oldItemId, SavedItemGeometry oldGeometry) {
addOperation(new ItemOperationMove(newItemView, oldItemId, oldGeometry));
}
public void storeItemState(Item item) {
addOperation(new ItemOperationState(item));
}
public void storePageState(Page page) {
addOperation(new PageOperationState(page));
}
private void addOperation(Operation operation) {
for(Operation op : mRedoOperations) {
op.clearTempStorage();
}
mRedoOperations.clear();
if(mUndoOperations.size() == mMaxSize) {
Operation op = mUndoOperations.removeFirst();
op.clearTempStorage();
}
mUndoOperations.add(operation);
notifyUndoListener();
}
private void notifyUndoListener() {
mListener.onUndoStackStateChanged(canUndo(), canRedo());
}
}

View file

@ -32,150 +32,152 @@ import android.content.Context;
* Although this preference only displays a title and a summary, it can nevertheless be used to manage complex settings by using the {@link LLPreferenceListView.OnLLPreferenceListViewEventListener#onLLPreferenceClicked(LLPreference)} event to catch clicks. This preference holds an arbitrary value (an object).
*/
public class LLPreference {
private int mId;
protected String mTitle;
protected String mSummary;
protected boolean mDisabled;
private final int mId;
protected String mTitle;
protected String mSummary;
protected boolean mDisabled;
protected boolean mIsLocked;
protected boolean mVisible = true;
protected Object mValue;
protected Object mDefaultValue;
protected Object mValue;
protected Object mDefaultValue;
/**
* @hide
/**
* @hide
*/
public LLPreference(Context context, int id, int title, int summary) {
this(context, id, title, summary, null, null);
}
public LLPreference(Context context, int id, int title, int summary) {
this(context, id, title, summary, null, null);
}
/**
* @hide
*/
public LLPreference(Context context, int id, int title, int summary, Object value, Object defaultValue) {
this(id, title==0 ? null : context.getString(title), summary==0 ? null : context.getString(summary), value, defaultValue);
}
/**
* @hide
*/
public LLPreference(Context context, int id, int title, int summary, Object value, Object defaultValue) {
this(id, title == 0 ? null : context.getString(title), summary == 0 ? null : context.getString(summary), value, defaultValue);
}
/**
* Create a new preference.
* @param id a unique number to identify the preference, use 0 if unused.
* @param title Displayed title.
* @param summary Displayed summary, use null for none.
* @param value Value for the preference.
/**
* Create a new preference.
*
* @param id a unique number to identify the preference, use 0 if unused.
* @param title Displayed title.
* @param summary Displayed summary, use null for none.
* @param value Value for the preference.
* @param defaultValue Default value if displaying the override checkbox. Use null if unused.
*/
public LLPreference(int id, String title, String summary, Object value, Object defaultValue) {
mId = id;
mTitle = title;
mSummary = summary;
public LLPreference(int id, String title, String summary, Object value, Object defaultValue) {
mId = id;
mTitle = title;
mSummary = summary;
setValue(value, defaultValue);
}
}
/**
* Set the value and optionally a default value.
* @param value the value stored by this preference
* @param defaultValue use null if unused
/**
* Set the value and optionally a default value.
*
* @param value the value stored by this preference
* @param defaultValue use null if unused
*/
public void setValue(Object value, Object defaultValue) {
mValue = value;
mDefaultValue = defaultValue;
}
/**
* Return the unique identifier.
/**
* Return the unique identifier.
*/
public int getId() {
return mId;
}
return mId;
}
/**
* Return the title.
/**
* Return the title.
*/
public String getTitle() {
return mTitle;
}
public String getTitle() {
return mTitle;
}
/**
* Set a new title.
/**
* Set a new title.
*/
public void setTitle(String title) {
mTitle = title;
}
mTitle = title;
}
/**
* Return the summary, if any.
/**
* Return the summary, if any.
*/
public String getSummary() {
return mSummary;
}
public String getSummary() {
return mSummary;
}
/**
* Set a new summary.
/**
* Set a new summary.
*/
public void setSummary(String summary) {
mSummary = summary;
}
/**
* Disable or enable the preference (it will be grayed out and not clickable when disabled)
/**
* Return true if the preference is currently disabled.
*/
public void setDisabled(boolean disabled) {
mDisabled = disabled;
}
/**
* Return true if the preference is currently disabled.
*/
public boolean isDisabled() {
return mDisabled;
}
/**
* Return true if this preference is showing the override checkbox.
*/
public boolean isShowingOverride() {
return mDefaultValue != null;
}
/**
* Return true if the value is different from the default value
*/
public boolean isOverriding() {
return !mValue.equals(mDefaultValue);
}
/**
* @hide
*/
public void setLocked(boolean locked) {
mIsLocked = locked;
public boolean isDisabled() {
return mDisabled;
}
/**
* @hide
*/
/**
* Disable or enable the preference (it will be grayed out and not clickable when disabled)
*/
public void setDisabled(boolean disabled) {
mDisabled = disabled;
}
/**
* Return true if this preference is showing the override checkbox.
*/
public boolean isShowingOverride() {
return mDefaultValue != null;
}
/**
* Return true if the value is different from the default value
*/
public boolean isOverriding() {
return !mValue.equals(mDefaultValue);
}
/**
* @hide
*/
public boolean isLocked() {
return mIsLocked;
}
/**
* Show or hide this preference.
/**
* @hide
*/
public void setVisible(boolean visible) {
mVisible = visible;
public void setLocked(boolean locked) {
mIsLocked = locked;
}
/**
* Return true is the preference is currently visible.
/**
* Return true is the preference is currently visible.
*/
public boolean isVisible() {
return mVisible;
}
/**
* Set the value of this preference with the default value.
*/
public void reset() {
mValue = mDefaultValue;
}
/**
* Show or hide this preference.
*/
public void setVisible(boolean visible) {
mVisible = visible;
}
/**
* Set the value of this preference with the default value.
*/
public void reset() {
mValue = mDefaultValue;
}
}

View file

@ -30,65 +30,68 @@ import android.content.Context;
* This preference is used to manage a color. It will display a color preview and a color picker when clicked.
*/
public class LLPreferenceColor extends LLPreference {
private boolean mHasAlpha;
private final boolean mHasAlpha;
/**
* Create a new color preference
* @param id a unique number to identify the preference, use 0 if unused.
* @param title Displayed title.
* @param summary Displayed summary, use null for none.
* @param color Color for the preference as a 32 bits ARGB value.
* @param default_color Default color if displaying the override checkbox. Use null if unused.
* @param has_alpha true to allow transparency setting
/**
* Create a new color preference
*
* @param id a unique number to identify the preference, use 0 if unused.
* @param title Displayed title.
* @param summary Displayed summary, use null for none.
* @param color Color for the preference as a 32 bits ARGB value.
* @param default_color Default color if displaying the override checkbox. Use null if unused.
* @param has_alpha true to allow transparency setting
*/
public LLPreferenceColor(int id, String title, String summary, int color, Integer default_color, boolean has_alpha) {
super(id, title, summary, color, default_color);
mHasAlpha = has_alpha;
}
public LLPreferenceColor(int id, String title, String summary, int color, Integer default_color, boolean has_alpha) {
super(id, title, summary, color, default_color);
mHasAlpha = has_alpha;
}
/**
* @hide
*/
public LLPreferenceColor(Context context, int id, int title, int summary, boolean has_alpha) {
super(context, id, title, summary);
mHasAlpha = has_alpha;
}
/**
* @hide
*/
public LLPreferenceColor(Context context, int id, int title, int summary, boolean has_alpha) {
super(context, id, title, summary);
mHasAlpha = has_alpha;
}
/**
* @hide
*/
/**
* @hide
*/
public LLPreferenceColor(Context context, int id, int title, int summary, int color, Integer default_color, boolean has_alpha) {
super(context, id, title, summary, Integer.valueOf(color), default_color);
mHasAlpha = has_alpha;
}
super(context, id, title, summary, Integer.valueOf(color), default_color);
mHasAlpha = has_alpha;
}
/**
* Return the currently selected color.
/**
* Return the currently selected color.
*/
public int getColor() {
return (Integer)mValue;
}
public int getColor() {
return (Integer) mValue;
}
/**
* Set this preference color.
* @param color a 32 bits ARGB value
/**
* Set this preference color.
*
* @param color a 32 bits ARGB value
*/
public void setColor(int color) {
mValue = Integer.valueOf(color);
}
public void setColor(int color) {
mValue = Integer.valueOf(color);
}
/**
* Set this preference default color.
* @param color a 32 bits ARGB value
*/
public void setDefaultColor(int color) {
mDefaultValue = Integer.valueOf(color);
}
/**
* Return true is this preference allows alpha configuration
/**
* Set this preference default color.
*
* @param color a 32 bits ARGB value
*/
public boolean hasAlpha() {
return mHasAlpha;
}
public void setDefaultColor(int color) {
mDefaultValue = Integer.valueOf(color);
}
/**
* Return true is this preference allows alpha configuration
*/
public boolean hasAlpha() {
return mHasAlpha;
}
}

View file

@ -31,7 +31,7 @@ import net.pierrox.lightning_launcher.data.EventAction;
public class LLPreferenceEventAction extends LLPreference {
private ActionsDescription mActions;
private final ActionsDescription mActions;
public LLPreferenceEventAction(Context context, int id, int title, EventAction value, EventAction defaultValue, ActionsDescription actions) {
super(id, context.getString(title), actions.getActionName(value.action), value, defaultValue);
@ -51,14 +51,14 @@ public class LLPreferenceEventAction extends LLPreference {
return (EventAction) mValue;
}
@Override
public void setValue(Object value, Object defaultValue) {
super.setValue(value, defaultValue);
public void setValue(EventAction ea) {
mValue = ea;
updateLabel();
}
public void setValue(EventAction ea) {
mValue = ea;
@Override
public void setValue(Object value, Object defaultValue) {
super.setValue(value, defaultValue);
updateLabel();
}
@ -68,7 +68,7 @@ public class LLPreferenceEventAction extends LLPreference {
private void updateLabel() {
EventAction ea = getValue();
if(ea == null || mActions == null) {
if (ea == null || mActions == null) {
setSummary("");
} else {
String more = ea.next == null ? "" : " (+)";

View file

@ -56,9 +56,8 @@ import net.margaritov.preference.colorpicker.ColorPickerDialog.OnColorChangedLis
import net.margaritov.preference.colorpicker.ColorPickerPanelView;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.LLAppPhone;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.script.api.Property;
import net.pierrox.lightning_launcher.engine.variable.Binding;
import net.pierrox.lightning_launcher.script.api.Property;
import net.pierrox.lightning_launcher.views.BoxEditorView;
import net.pierrox.lightning_launcher.views.BoxEditorView.OnBoxEditorEventListener;
import net.pierrox.lightning_launcher_extreme.R;
@ -71,238 +70,247 @@ import java.util.Arrays;
*/
public class LLPreferenceListView extends ListView implements OnItemClickListener, OnColorChangedListener, DialogInterface.OnClickListener, AdapterView.OnItemLongClickListener, DialogPreferenceSlider.OnDialogPreferenceSliderListener {
public interface OnLLPreferenceListViewEventListener {
public void onLLPreferenceClicked(LLPreference preference);
public void onLLPreferenceLongClicked(LLPreference preference);
public void onLLPreferenceChanged(LLPreference preference);
/** @hide */ public void onLLPreferenceBindingRemoved(LLPreferenceBinding preference);
}
private LLPreferenceColor mDialogColorPreference;
private LLPreferenceSlider mDialogSliderPreference;
private LLPreferenceList mDialogListPreference;
private LLPreferenceText mDialogTextPreference;
private LLPreference mDialogPreference;
private Dialog mDialog;
private PrefAdapter mAdapter;
private LLPreferenceColor mDialogColorPreference;
private LLPreferenceSlider mDialogSliderPreference;
private LLPreferenceList mDialogListPreference;
private LLPreferenceText mDialogTextPreference;
private LLPreference mDialogPreference;
private Dialog mDialog;
private PrefAdapter mAdapter;
private boolean mCompactMode;
private boolean mDisplayOverride;
private OnLLPreferenceListViewEventListener mOnLLPreferenceListViewEventListener;
private OnLLPreferenceListViewEventListener mOnLLPreferenceListViewEventListener;
/**
* Default constructor.
*/
public LLPreferenceListView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnItemClickListener(this);
setOnItemLongClickListener(this);
}
/**
* @hide
/**
* Default constructor.
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Context context = getContext();
LLPreference p = (LLPreference)parent.getItemAtPosition(position);
if(p.isLocked()) {
public LLPreferenceListView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnItemClickListener(this);
setOnItemLongClickListener(this);
}
/**
* @hide
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Context context = getContext();
LLPreference p = (LLPreference) parent.getItemAtPosition(position);
if (p.isLocked()) {
LLApp.get().showFeatureLockedDialog(context);
return;
}
if(p.isDisabled()) {
return;
}
if(mDialog != null) {
mDialog.dismiss();
}
mDialog = null;
if(p instanceof LLPreferenceCheckBox) {
LLPreferenceCheckBox cbp = (LLPreferenceCheckBox)p;
cbp.setChecked(!cbp.isChecked());
mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(cbp);
} else if(p instanceof LLPreferenceColor) {
mDialogColorPreference = (LLPreferenceColor)p;
ColorPickerDialog color_picker_dialog = new ColorPickerDialog(context, mDialogColorPreference.getColor());
color_picker_dialog.setAlphaSliderVisible(mDialogColorPreference.hasAlpha());
color_picker_dialog.setOnColorChangedListener(this);
mDialog = color_picker_dialog;
} else if(p instanceof LLPreferenceSlider) {
mDialogSliderPreference = (LLPreferenceSlider)p;
LLPreferenceSlider sp = mDialogSliderPreference;
DialogPreferenceSlider slider_dialog = new DialogPreferenceSlider(context, sp.getValue(), sp.getValueType()== LLPreferenceSlider.ValueType.FLOAT, sp.getMinValue(), sp.getMaxValue(), sp.getInterval(), sp.getUnit(), this);
slider_dialog.setTitle(sp.getTitle());
mDialog = slider_dialog;
} else if(p instanceof LLPreferenceText) {
mDialogTextPreference = (LLPreferenceText)p;
if (p.isDisabled()) {
return;
}
if (mDialog != null) {
mDialog.dismiss();
}
mDialog = null;
if (p instanceof LLPreferenceCheckBox) {
LLPreferenceCheckBox cbp = (LLPreferenceCheckBox) p;
cbp.setChecked(!cbp.isChecked());
mAdapter.notifyDataSetChanged();
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(cbp);
} else if (p instanceof LLPreferenceColor) {
mDialogColorPreference = (LLPreferenceColor) p;
ColorPickerDialog color_picker_dialog = new ColorPickerDialog(context, mDialogColorPreference.getColor());
color_picker_dialog.setAlphaSliderVisible(mDialogColorPreference.hasAlpha());
color_picker_dialog.setOnColorChangedListener(this);
mDialog = color_picker_dialog;
} else if (p instanceof LLPreferenceSlider) {
mDialogSliderPreference = (LLPreferenceSlider) p;
LLPreferenceSlider sp = mDialogSliderPreference;
DialogPreferenceSlider slider_dialog = new DialogPreferenceSlider(context, sp.getValue(), sp.getValueType() == LLPreferenceSlider.ValueType.FLOAT, sp.getMinValue(), sp.getMaxValue(), sp.getInterval(), sp.getUnit(), this);
slider_dialog.setTitle(sp.getTitle());
mDialog = slider_dialog;
} else if (p instanceof LLPreferenceText) {
mDialogTextPreference = (LLPreferenceText) p;
LLPreferenceText tp = mDialogTextPreference;
LLPreferenceTextDialog text_dialog = new LLPreferenceTextDialog(context, tp.getValue());
text_dialog.setTitle(tp.getTitle());
mDialog = text_dialog;
} else if(p instanceof LLPreferenceList) {
mDialogListPreference = (LLPreferenceList)p;
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(mDialogListPreference.getTitle());
builder.setSingleChoiceItems(mDialogListPreference.getLabels(), mDialogListPreference.getValueIndex(), this);
builder.setNegativeButton(android.R.string.cancel, null);
mDialog = builder.create();
} else if (p instanceof LLPreferenceList) {
mDialogListPreference = (LLPreferenceList) p;
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(mDialogListPreference.getTitle());
builder.setSingleChoiceItems(mDialogListPreference.getLabels(), mDialogListPreference.getValueIndex(), this);
builder.setNegativeButton(android.R.string.cancel, null);
mDialog = builder.create();
}
if(mDialog != null) {
if (mDialog != null) {
mDialogPreference = p;
mDialog.show();
}
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceClicked(p);
}
mDialog.show();
}
/**
* @hide
*/
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
LLPreference p = (LLPreference)parent.getItemAtPosition(position);
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceLongClicked(p);
return true;
}
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceClicked(p);
}
/**
* @hide
*/
@Override
public void onColorChanged(int color) {
mDialogColorPreference.setColor(color);
mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogColorPreference);
}
/**
* @hide
*/
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
LLPreference p = (LLPreference) parent.getItemAtPosition(position);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceLongClicked(p);
return true;
}
/**
* @hide
*/
/**
* @hide
*/
@Override
public void onColorChanged(int color) {
mDialogColorPreference.setColor(color);
mAdapter.notifyDataSetChanged();
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogColorPreference);
}
/**
* @hide
*/
@Override
public void onColorDialogSelected(int color) {
// pass
}
/**
* @hide
*/
/**
* @hide
*/
@Override
public void onColorDialogCanceled() {
// pass
}
/**
* @hide
*/
/**
* @hide
*/
@Override
public void onClick(DialogInterface dialog, int which) {
mDialogListPreference.setValueIndex(which);
dialog.dismiss();
mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogListPreference);
}
public void onClick(DialogInterface dialog, int which) {
mDialogListPreference.setValueIndex(which);
dialog.dismiss();
mAdapter.notifyDataSetChanged();
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogListPreference);
}
/**
* Set a listener for preference clicked, long clicked, changed events
/**
* Set a listener for preference clicked, long clicked, changed events
*/
public void setListener(OnLLPreferenceListViewEventListener listener) {
mOnLLPreferenceListViewEventListener = listener;
}
public void setListener(OnLLPreferenceListViewEventListener listener) {
mOnLLPreferenceListViewEventListener = listener;
}
/**
* Set the list of preferences to display in this listview.
/**
* @hide
*/
public void setPreferences(LLPreference[] preferences) {
setPreferences(new ArrayList<>(Arrays.asList(preferences)));
}
/**
* @hide
*/
public void setPreferences(ArrayList<LLPreference> preferences) {
mAdapter = new PrefAdapter(getContext(), 0, preferences);
setAdapter(mAdapter);
}
/**
* @hide
*/
public ArrayList<LLPreference> getPreferences() {
return mAdapter == null ? null : mAdapter.getObjects();
}
/**
* Request a manual refresh.
*/
public void refresh() {
int count = mAdapter.getCount();
mAdapter.notifyDataSetChanged();
if(mAdapter.getCount() != count) {
// this is needed to force the ListView to keep its children views in sync by clearing its recycler
setAdapter(mAdapter);
}
}
/**
* Set the list of preferences to display in this listview.
*/
public void setPreferences(LLPreference[] preferences) {
setPreferences(new ArrayList<>(Arrays.asList(preferences)));
}
/**
* @hide
*/
/**
* @hide
*/
public void setPreferences(ArrayList<LLPreference> preferences) {
mAdapter = new PrefAdapter(getContext(), 0, preferences);
setAdapter(mAdapter);
}
/**
* Request a manual refresh.
*/
public void refresh() {
int count = mAdapter.getCount();
mAdapter.notifyDataSetChanged();
if (mAdapter.getCount() != count) {
// this is needed to force the ListView to keep its children views in sync by clearing its recycler
setAdapter(mAdapter);
}
}
/**
* @hide
*/
@Override
public void onDialogPreferenceSliderValueSet(float value) {
mDialogSliderPreference.setValue(value);
mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogSliderPreference);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogSliderPreference);
}
/**
* @hide
*/
/**
* @hide
*/
@Override
public void onDialogPreferenceSliderCancel() {
// pass
}
/**
* Use a mode where preferences are displayed using a more compact layout
* @param compactMode true to shrink preferences and display more preferences in a screen.
/**
* Use a mode where preferences are displayed using a more compact layout
*
* @param compactMode true to shrink preferences and display more preferences in a screen.
*/
public void setCompactMode(boolean compactMode) {
mCompactMode = compactMode;
}
/**
* Select whether to display the override checkbow at the left of the preference. This implies that preferences have a default value so that this override checkbox can be managed properly.
*/
/**
* Select whether to display the override checkbow at the left of the preference. This implies that preferences have a default value so that this override checkbox can be managed properly.
*/
public void setDisplayOverride(boolean displayOverride) {
mDisplayOverride = displayOverride;
if(mAdapter != null) {
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
private class PrefAdapter extends ArrayAdapter<LLPreference> implements OnCheckedChangeListener, OnBoxEditorEventListener, OnClickListener {
private int mPrefLayout;
private int mPrefCategoryLayout;
private int mPrefListWidgetLayout;
private float mPrefSizeCategory;
private float mPrefSizeTitle;
private float mPrefSizeSummary;
private LayoutInflater mLayoutInflater;
private float mDensity;
public interface OnLLPreferenceListViewEventListener {
void onLLPreferenceClicked(LLPreference preference);
void onLLPreferenceLongClicked(LLPreference preference);
void onLLPreferenceChanged(LLPreference preference);
/**
* @hide
*/
void onLLPreferenceBindingRemoved(LLPreferenceBinding preference);
}
private class PrefAdapter extends ArrayAdapter<LLPreference> implements OnCheckedChangeListener, OnBoxEditorEventListener, OnClickListener {
private final int mPrefLayout;
private final int mPrefCategoryLayout;
private final int mPrefListWidgetLayout;
private final float mPrefSizeCategory;
private final float mPrefSizeTitle;
private final float mPrefSizeSummary;
private final LayoutInflater mLayoutInflater;
private final float mDensity;
ArrayList<LLPreference> mObjects;
ArrayList<LLPreference> mFilteredObjects;
public PrefAdapter(Context context, int textViewResourceId, ArrayList<LLPreference> objects) {
super(context, textViewResourceId);
mPrefLayout = new Preference(context).getLayoutResource();
mPrefCategoryLayout = new PreferenceCategory(context).getLayoutResource();
mPrefListWidgetLayout = new ListPreference(context).getWidgetLayoutResource();
mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
public PrefAdapter(Context context, int textViewResourceId, ArrayList<LLPreference> objects) {
super(context, textViewResourceId);
mPrefLayout = new Preference(context).getLayoutResource();
mPrefCategoryLayout = new PreferenceCategory(context).getLayoutResource();
mPrefListWidgetLayout = new ListPreference(context).getWidgetLayoutResource();
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resources resources = getResources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
mDensity = displayMetrics.density;
@ -312,24 +320,24 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
mPrefSizeSummary = resources.getDimensionPixelSize(R.dimen.pref_size_summary) / scaledDensity;
mObjects = objects;
filterObjects();
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LLPreference p = getItem(position);
boolean is_category = p instanceof LLPreferenceCategory;
if(p instanceof LLPreferenceBox) {
if(convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.box_config, null);
((TextView)convertView.findViewById(R.id.box_h)).setText(R.string.b_hint);
((BoxEditorView)convertView.findViewById(R.id.box)).setOnBoxEditorEventListener(p, this);
}
} else {
if(convertView == null) {
View preference_view = mLayoutInflater.inflate(is_category ? mPrefCategoryLayout : mPrefLayout, null);
if(mCompactMode) {
TextView title_view = (TextView) preference_view.findViewById(android.R.id.title);
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LLPreference p = getItem(position);
boolean is_category = p instanceof LLPreferenceCategory;
if (p instanceof LLPreferenceBox) {
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.box_config, null);
((TextView) convertView.findViewById(R.id.box_h)).setText(R.string.b_hint);
((BoxEditorView) convertView.findViewById(R.id.box)).setOnBoxEditorEventListener(p, this);
}
} else {
if (convertView == null) {
View preference_view = mLayoutInflater.inflate(is_category ? mPrefCategoryLayout : mPrefLayout, null);
if (mCompactMode) {
TextView title_view = preference_view.findViewById(android.R.id.title);
if (is_category) {
title_view.setTextSize(mPrefSizeCategory);
} else {
@ -339,68 +347,68 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
preference_view.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.pref_height));
}
}
preference_view = ((LLAppPhone)LLApp.get()).managePreferenceViewLockedFlag(p, preference_view);
View icon = preference_view.findViewById(android.R.id.icon);
if(icon != null) {
((View)icon.getParent()).setVisibility(View.GONE);
}
ViewGroup widget_frame = (ViewGroup) preference_view.findViewById(android.R.id.widget_frame);
if(is_category) {
//preference_view.setEnabled(false);
} else if(p instanceof LLPreferenceList) {
if(mPrefListWidgetLayout != 0) {
mLayoutInflater.inflate(mPrefListWidgetLayout, widget_frame);
}
} else if(p instanceof LLPreferenceCheckBox) {
CheckBox widget = new CheckBox(getContext());
widget.setFocusable(false);
widget.setClickable(false);
widget_frame.addView(widget);
} else if(p instanceof LLPreferenceColor) {
View v = new ColorPickerPanelView(getContext());
int s = (int)(30*mDensity);
v.setLayoutParams(new FrameLayout.LayoutParams(s, s));
widget_frame.addView(v);
} else if(p instanceof LLPreferenceSlider) {
preference_view = ((LLAppPhone) LLApp.get()).managePreferenceViewLockedFlag(p, preference_view);
View icon = preference_view.findViewById(android.R.id.icon);
if (icon != null) {
((View) icon.getParent()).setVisibility(View.GONE);
}
ViewGroup widget_frame = preference_view.findViewById(android.R.id.widget_frame);
if (is_category) {
//preference_view.setEnabled(false);
} else if (p instanceof LLPreferenceList) {
if (mPrefListWidgetLayout != 0) {
mLayoutInflater.inflate(mPrefListWidgetLayout, widget_frame);
}
} else if (p instanceof LLPreferenceCheckBox) {
CheckBox widget = new CheckBox(getContext());
widget.setFocusable(false);
widget.setClickable(false);
widget_frame.addView(widget);
} else if (p instanceof LLPreferenceColor) {
View v = new ColorPickerPanelView(getContext());
int s = (int) (30 * mDensity);
v.setLayoutParams(new FrameLayout.LayoutParams(s, s));
widget_frame.addView(v);
} else if (p instanceof LLPreferenceSlider) {
mLayoutInflater.inflate(R.layout.llpref_slider, widget_frame);
} else if(p instanceof LLPreferenceBinding) {
} else if (p instanceof LLPreferenceBinding) {
Button widget = new Button(getContext());
widget.setText("4");
widget.setTypeface(LLApp.get().getIconsTypeface());
widget.setOnClickListener(this);
widget.setFocusable(false);
widget_frame.addView(widget);
}
convertView = mLayoutInflater.inflate(R.layout.override_preference, null, false);
CheckBox override = (CheckBox)convertView.findViewById(R.id.override);
override.setOnCheckedChangeListener(this);
LinearLayout container = (LinearLayout)convertView.findViewById(R.id.content);
container.addView(preference_view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
View override_g = convertView.findViewById(R.id.override_g);
TextView override_t = (TextView) override_g.findViewById(R.id.override_t);
CheckBox override = (CheckBox)convertView.findViewById(R.id.override);
override.setTag(p);
if(!is_category && p.isShowingOverride() && mDisplayOverride) {
boolean overriding = p.isOverriding();
boolean enabled = overriding && !p.isDisabled();
override.setChecked(overriding);
override.setEnabled(enabled);
}
convertView = mLayoutInflater.inflate(R.layout.override_preference, null, false);
CheckBox override = convertView.findViewById(R.id.override);
override.setOnCheckedChangeListener(this);
LinearLayout container = convertView.findViewById(R.id.content);
container.addView(preference_view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
View override_g = convertView.findViewById(R.id.override_g);
TextView override_t = override_g.findViewById(R.id.override_t);
CheckBox override = convertView.findViewById(R.id.override);
override.setTag(p);
if (!is_category && p.isShowingOverride() && mDisplayOverride) {
boolean overriding = p.isOverriding();
boolean enabled = overriding && !p.isDisabled();
override.setChecked(overriding);
override.setEnabled(enabled);
override_t.setEnabled(enabled);
override_t.setText(R.string.ovr_custom);
override_g.setVisibility(View.VISIBLE);
} else {
override_g.setVisibility(is_category || !mDisplayOverride ? View.GONE : View.INVISIBLE);
}
override_g.setVisibility(View.VISIBLE);
} else {
override_g.setVisibility(is_category || !mDisplayOverride ? View.GONE : View.INVISIBLE);
}
String title;
if(p instanceof LLPreferenceBinding) {
Binding b = ((LLPreferenceBinding)p).getValue();
if (p instanceof LLPreferenceBinding) {
Binding b = ((LLPreferenceBinding) p).getValue();
Property prop = Property.getByName(b.target);
title = prop == null ? p.getTitle() : prop.getLabel();
override.setChecked(b.enabled);
@ -412,65 +420,65 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
title = p.getTitle();
}
((TextView) convertView.findViewById(android.R.id.title)).setText(title);
if(!is_category) {
String s = p.getSummary();
TextView vs = (TextView) convertView.findViewById(android.R.id.summary);
if(s == null) {
vs.setVisibility(View.GONE);
} else {
vs.setVisibility(View.VISIBLE);
vs.setText(s);
}
}
ViewGroup widget_frame = (ViewGroup) convertView.findViewById(android.R.id.widget_frame);
if(is_category) {
} else if(p instanceof LLPreferenceCheckBox) {
CheckBox widget = (CheckBox) widget_frame.getChildAt(0);
widget.setChecked(((LLPreferenceCheckBox)p).isChecked());
} else if(p instanceof LLPreferenceColor) {
if (!is_category) {
String s = p.getSummary();
TextView vs = convertView.findViewById(android.R.id.summary);
if (s == null) {
vs.setVisibility(View.GONE);
} else {
vs.setVisibility(View.VISIBLE);
vs.setText(s);
}
}
ViewGroup widget_frame = convertView.findViewById(android.R.id.widget_frame);
if (is_category) {
} else if (p instanceof LLPreferenceCheckBox) {
CheckBox widget = (CheckBox) widget_frame.getChildAt(0);
widget.setChecked(((LLPreferenceCheckBox) p).isChecked());
} else if (p instanceof LLPreferenceColor) {
// View color_preview = widget_frame.findViewById(R.id.color_preview);
// color_preview.setBackgroundColor(((LLPreferenceColor)p).getColor());
ColorPickerPanelView v = (ColorPickerPanelView)widget_frame.getChildAt(0);
v.setColor(((LLPreferenceColor)p).getColor());
} else if(p instanceof LLPreferenceSlider) {
TextView tv_value = (TextView) widget_frame.findViewById(R.id.slider_value);
TextView tv_unit = (TextView) widget_frame.findViewById(R.id.slider_unit);
ColorPickerPanelView v = (ColorPickerPanelView) widget_frame.getChildAt(0);
v.setColor(((LLPreferenceColor) p).getColor());
} else if (p instanceof LLPreferenceSlider) {
TextView tv_value = widget_frame.findViewById(R.id.slider_value);
TextView tv_unit = widget_frame.findViewById(R.id.slider_unit);
LLPreferenceSlider sp = (LLPreferenceSlider) p;
String unit = sp.getUnit();
tv_value.setText(DialogPreferenceSlider.valueAsText(sp.getValueType()== LLPreferenceSlider.ValueType.FLOAT, unit, sp.getValue(), sp.getInterval()));
tv_value.setText(DialogPreferenceSlider.valueAsText(sp.getValueType() == LLPreferenceSlider.ValueType.FLOAT, unit, sp.getValue(), sp.getInterval()));
tv_unit.setText(sp.getUnit());
} else if(p instanceof LLPreferenceBinding) {
} else if (p instanceof LLPreferenceBinding) {
widget_frame.getChildAt(0).setTag(p);
}
}
if(!is_category) {
// should use dimensions from some resource
convertView.setPadding(15, 0, 10, 0);
}
}
}
setEnabledStateOnViews(convertView, !p.isDisabled());
return convertView;
}
private void setEnabledStateOnViews(View v, boolean enabled) {
v.setEnabled(enabled);
if (!is_category) {
// should use dimensions from some resource
convertView.setPadding(15, 0, 10, 0);
}
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
View c = vg.getChildAt(i);
// do not change the override checkbox
int id=c.getId();
if(id!=R.id.override && id!=R.id.override_t) {
setEnabledStateOnViews(c, enabled);
}
}
}
}
setEnabledStateOnViews(convertView, !p.isDisabled());
return convertView;
}
private void setEnabledStateOnViews(View v, boolean enabled) {
v.setEnabled(enabled);
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
View c = vg.getChildAt(i);
// do not change the override checkbox
int id = c.getId();
if (id != R.id.override && id != R.id.override_t) {
setEnabledStateOnViews(c, enabled);
}
}
}
}
@Override
public void notifyDataSetChanged() {
@ -489,73 +497,76 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
}
@Override
public boolean isEnabled(int position) {
return !(getItem(position) instanceof LLPreferenceCategory);
}
public boolean isEnabled(int position) {
return !(getItem(position) instanceof LLPreferenceCategory);
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public int getItemViewType(int position) {
LLPreference p = getItem(position);
if(p instanceof LLPreferenceCategory) {
return 1;
} else if(p instanceof LLPreferenceCheckBox) {
return 2;
} else if(p instanceof LLPreferenceColor) {
return 3;
} else if(p instanceof LLPreferenceList) {
return 4;
} else if(p instanceof LLPreferenceSlider) {
return 5;
} else if(p instanceof LLPreferenceBox) {
return 6;
} else if(p instanceof LLPreferenceBinding) {
return 7;
}
return 0;
}
@Override
public int getItemViewType(int position) {
LLPreference p = getItem(position);
if (p instanceof LLPreferenceCategory) {
return 1;
} else if (p instanceof LLPreferenceCheckBox) {
return 2;
} else if (p instanceof LLPreferenceColor) {
return 3;
} else if (p instanceof LLPreferenceList) {
return 4;
} else if (p instanceof LLPreferenceSlider) {
return 5;
} else if (p instanceof LLPreferenceBox) {
return 6;
} else if (p instanceof LLPreferenceBinding) {
return 7;
}
return 0;
}
@Override
public int getViewTypeCount() {
// base pref, category, checkbox, color, slider, list, box, binding
return 8;
}
@Override
public int getViewTypeCount() {
// base pref, category, checkbox, color, slider, list, box, binding
return 8;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
LLPreference p = (LLPreference)buttonView.getTag();
if(p instanceof LLPreferenceBinding) {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
LLPreference p = (LLPreference) buttonView.getTag();
if (p instanceof LLPreferenceBinding) {
Binding binding = ((LLPreferenceBinding) p).getValue();
if(binding.enabled != isChecked) {
if (binding.enabled != isChecked) {
binding.enabled = isChecked;
if (mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
}
} else {
if (!isChecked) {
if (p.isOverriding()) {
p.reset();
notifyDataSetChanged();
if (mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
}
}
}
}
}
@Override
public void onBoxSelectionChanged(Object token, int selection) {
LLPreferenceBox p = (LLPreferenceBox)token;
p.setSelection(selection);
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
}
@Override
public void onBoxSelectionChanged(Object token, int selection) {
LLPreferenceBox p = (LLPreferenceBox) token;
p.setSelection(selection);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
}
private void filterObjects() {
mFilteredObjects = new ArrayList<>();
for(LLPreference p : mObjects) {
if(p.isVisible()) {
for (LLPreference p : mObjects) {
if (p.isVisible()) {
mFilteredObjects.add(p);
}
}
@ -564,7 +575,8 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
@Override
public void onClick(View v) {
LLPreferenceBinding p = (LLPreferenceBinding) v.getTag();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceBindingRemoved(p);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceBindingRemoved(p);
}
public ArrayList<LLPreference> getObjects() {
@ -573,7 +585,7 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
}
private class LLPreferenceTextDialog extends AlertDialog implements DialogInterface.OnClickListener {
private String mValue;
private final String mValue;
private EditText mDialogEditText;
public LLPreferenceTextDialog(Context context, String value) {
@ -602,11 +614,12 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
@Override
public void onClick(DialogInterface dialog, int which) {
switch(which) {
switch (which) {
case BUTTON_POSITIVE:
mDialogTextPreference.setValue(mDialogEditText.getText().toString());
mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogTextPreference);
if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogTextPreference);
break;
}
}

View file

@ -30,64 +30,60 @@ import android.content.Context;
* This preference is used to manage number settings, using a slider and -/+ buttons.
*/
public class LLPreferenceSlider extends LLPreference {
/**
* @hide
*/
public enum ValueType { INT, FLOAT }
private final float mMinValue;
private final float mMaxValue;
private final float mInterval;
private final String mUnit;
private ValueType mValueType;
private ValueType mValueType;
private float mMinValue;
private float mMaxValue;
private float mInterval;
private String mUnit;
/**
* @hide
*/
public LLPreferenceSlider(Context context, int id, int title, int summary, ValueType value_type, float min, float max, float interval, String unit) {
super(context, id, title, summary);
/**
* @hide
*/
public LLPreferenceSlider(Context context, int id, int title, int summary, ValueType value_type, float min, float max, float interval, String unit) {
super(context, id, title, summary);
mValueType = value_type;
mMinValue = min;
mMaxValue = max;
mInterval = interval;
mUnit = unit;
}
}
/**
* Construct a slider preference
* @param id a unique number to identify the preference, use 0 if unused.
* @param title Displayed title.
* @param summary Displayed summary, use null for none.
* @param value Value for the preference.
* @param defaultValue Default value if displaying the override checkbox. Use null if unused.
* @param value_type one of INT (integer) or FLOAT (floating point value)
* @param min minimum value for the slider
* @param max maximum value for the slider
* @param interval step to use when using +/- buttons
* @param unit optional text to display units
/**
* Construct a slider preference
*
* @param id a unique number to identify the preference, use 0 if unused.
* @param title Displayed title.
* @param summary Displayed summary, use null for none.
* @param value Value for the preference.
* @param defaultValue Default value if displaying the override checkbox. Use null if unused.
* @param value_type one of INT (integer) or FLOAT (floating point value)
* @param min minimum value for the slider
* @param max maximum value for the slider
* @param interval step to use when using +/- buttons
* @param unit optional text to display units
*/
public LLPreferenceSlider(int id, String title, String summary, float value, Float default_value, String value_type, float min, float max, float interval, String unit) {
super(id, title, summary, null, null);
super(id, title, summary, null, null);
try {
mValueType = ValueType.valueOf(value_type);
} catch (IllegalArgumentException e) {
mValueType = ValueType.FLOAT;
}
try {
mValueType = ValueType.valueOf(value_type);
} catch (IllegalArgumentException e) {
mValueType = ValueType.FLOAT;
}
mMinValue = min;
mMaxValue = max;
mInterval = interval;
mUnit = unit;
setValue(value, default_value);
}
}
/**
* @hide
*/
/**
* @hide
*/
public LLPreferenceSlider(Context context, int id, int title, int summary, float value, Float default_value, ValueType value_type, float min, float max, float interval, String unit) {
super(context, id, title, summary);
super(context, id, title, summary);
mValueType = value_type;
mMinValue = min;
@ -96,70 +92,75 @@ public class LLPreferenceSlider extends LLPreference {
mUnit = unit;
setValue(value, default_value);
}
}
/**
* Return the value as a float, no matter what the input type is (integer or floating point)
/**
* Return the value as a float, no matter what the input type is (integer or floating point)
*/
public float getValue() {
return (Float)mValue;
}
return (Float) mValue;
}
public void setValue(float value) {
mValue = Float.valueOf(value);
}
public void setValue(float value) {
mValue = Float.valueOf(value);
}
/**
* @hide
*/
/**
* @hide
*/
public void setValue(float value, Float default_value) {
super.setValue(Float.valueOf(value), default_value);
}
/**
* @hide
*/
public void setDefaultValue(float value) {
mDefaultValue = Float.valueOf(value);
}
// public void setValue(float value, Float default_value) {
// super.setValue(Float.valueOf(value), default_value);
// }
/**
* @hide
*/
public void setDefaultValue(float value) {
mDefaultValue = Float.valueOf(value);
}
/**
* @hide
*/
public ValueType getValueType() {
return mValueType;
}
/**
* @hide
*/
public ValueType getValueType() {
return mValueType;
}
/**
* @hide
*/
public float getMinValue() {
return mMinValue;
}
/**
* @hide
*/
public float getMinValue() {
return mMinValue;
}
/**
* @hide
*/
public float getMaxValue() {
return mMaxValue;
}
/**
* @hide
*/
public float getMaxValue() {
return mMaxValue;
}
/**
* @hide
*/
public float getInterval() {
return mInterval;
}
/**
* @hide
*/
public float getInterval() {
return mInterval;
}
/**
* @hide
*/
public String getUnit() {
return mUnit;
}
/**
* @hide
*/
public String getUnit() {
return mUnit;
}
/**
* @hide
*/
public enum ValueType {INT, FLOAT}
}

View file

@ -74,42 +74,22 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
public static final int AI_BOOKMARK = 16;
public static final int AI_LIGHTNING_ACTION = 17;
public static final int AI_CUSTOM_VIEW = 18;
public interface AddItemDialogInterface {
boolean isDialogAddItemEnabled(int id);
void onBuiltinItemClicked(int id);
void onPluginClicked(Plugin plugin);
void onPluginLongClicked(Plugin plugin);
}
public static class Plugin {
public CharSequence label;
public Drawable icon;
public Intent intent;
public Plugin(CharSequence label, Drawable icon, Intent intent) {
this.label = label;
this.icon = icon;
this.intent = intent;
}
}
private AddItemDialogInterface mAddItemDialogInterface;
private LayoutInflater mInflater;
private final AddItemDialogInterface mAddItemDialogInterface;
private final LayoutInflater mInflater;
public AddItemDialog(final Context context, boolean showPlugins, final AddItemDialogInterface addItemDialogInterface) {
super(context);
mAddItemDialogInterface = addItemDialogInterface;
String[] labels=context.getResources().getStringArray(R.array.dialog_action_values);
String[] labels = context.getResources().getStringArray(R.array.dialog_action_values);
mInflater = LayoutInflater.from(context);
final ViewGroup content = (ViewGroup) mInflater.inflate(R.layout.add_dialog, null);
final MyViewPager pager = (MyViewPager) content.findViewById(R.id.pager);
ViewGroup builtinsView = (ViewGroup) content.findViewById(R.id.builtins);
final ListView pluginsListView = (ListView) content.findViewById(R.id.plugins);
final TabHost tabHost = (TabHost) content.findViewById(R.id.tab);
final MyViewPager pager = content.findViewById(R.id.pager);
ViewGroup builtinsView = content.findViewById(R.id.builtins);
final ListView pluginsListView = content.findViewById(R.id.plugins);
final TabHost tabHost = content.findViewById(R.id.tab);
tabHost.setup();
tabHost.addTab(tabHost.newTabSpec("B").setIndicator(context.getString(R.string.ad_b)).setContent(R.id.empty));
tabHost.addTab(tabHost.newTabSpec("P").setIndicator(context.getString(R.string.ad_p)).setContent(R.id.empty));
@ -121,7 +101,8 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
});
pager.setOnPageChangeListener(new MyViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
@ -129,7 +110,8 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
}
@Override
public void onPageScrollStateChanged(int state) { }
public void onPageScrollStateChanged(int state) {
}
});
pluginsListView.setOnItemClickListener(this);
@ -137,7 +119,7 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
setView(content);
if(!showPlugins) {
if (!showPlugins) {
tabHost.setVisibility(View.GONE);
pager.removeViewAt(1);
} else {
@ -225,18 +207,18 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
private ViewGroup addDialogAddCategory(ViewGroup root, int title) {
View cat = mInflater.inflate(R.layout.add_dialog_cat, root, false);
((TextView)cat.findViewById(R.id.title)).setText(title);
((TextView) cat.findViewById(R.id.title)).setText(title);
root.addView(cat);
return (ViewGroup) cat.findViewById(R.id.content);
return cat.findViewById(R.id.content);
}
private void addDialogAddItem(ViewGroup root, String label, String icon, int id) {
View item = mInflater.inflate(R.layout.add_dialog_item, root, false);
TextView i = (TextView)item.findViewById(R.id.icon);
TextView i = item.findViewById(R.id.icon);
i.setText(icon);
LLAppPhone app = (LLAppPhone) LLApp.get();
i.setTypeface(app.getIconsTypeface());
((TextView)item.findViewById(R.id.label)).setText(label);
((TextView) item.findViewById(R.id.label)).setText(label);
item.setOnClickListener(this);
item.setTag(id);
Utils.setEnabledStateOnViews(item, mAddItemDialogInterface.isDialogAddItemEnabled(id));
@ -245,8 +227,30 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
root.addView(item);
}
public interface AddItemDialogInterface {
boolean isDialogAddItemEnabled(int id);
void onBuiltinItemClicked(int id);
void onPluginClicked(Plugin plugin);
void onPluginLongClicked(Plugin plugin);
}
public static class Plugin {
public CharSequence label;
public Drawable icon;
public Intent intent;
public Plugin(CharSequence label, Drawable icon, Intent intent) {
this.label = label;
this.icon = icon;
this.intent = intent;
}
}
private static class PluginAdapter extends ArrayAdapter<Plugin> {
private LayoutInflater mLayoutInflater;
private final LayoutInflater mLayoutInflater;
public PluginAdapter(Context context, List<Plugin> objects) {
super(context, 0, objects);
@ -261,7 +265,7 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
Plugin plugin = getItem(position);
CheckedTextView line1 = (CheckedTextView) convertView.findViewById(android.R.id.text1);
CheckedTextView line1 = convertView.findViewById(android.R.id.text1);
line1.setText(plugin.label);
convertView.findViewById(android.R.id.text2).setVisibility(View.GONE);
((ImageView) convertView.findViewById(android.R.id.icon)).setImageDrawable(plugin.icon);

View file

@ -38,6 +38,10 @@ import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import net.pierrox.android.lsvg.SvgDrawable;
import net.pierrox.android.lsvg.SvgElement;
import net.pierrox.android.lsvg.SvgGroup;
import net.pierrox.android.lsvg.SvgPath;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.engine.LightningEngine;
@ -50,14 +54,9 @@ import net.pierrox.lightning_launcher.views.IconView;
import net.pierrox.lightning_launcher.views.SharedAsyncGraphicsDrawable;
import net.pierrox.lightning_launcher.views.item.ItemView;
import net.pierrox.lightning_launcher.views.item.ShortcutView;
import net.pierrox.android.lsvg.SvgDrawable;
import net.pierrox.android.lsvg.SvgElement;
import net.pierrox.android.lsvg.SvgGroup;
import net.pierrox.android.lsvg.SvgPath;
import net.pierrox.lightning_launcher_extreme.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@ -65,19 +64,17 @@ import java.util.List;
import java.util.Map;
public class BindingEditDialog extends AlertDialog implements DialogInterface.OnClickListener, View.OnClickListener {
public interface OnBindingEditDialogListener {
public void onBindingEdited(Binding binding, boolean open_in_script_editor);
}
private Binding mInitValue;
private Binding[] mOtherBindings;
private static final String ROOT_KEY = "r";
private static final String CHILD_KEY = "c";
private final Binding mInitValue;
private final Binding[] mOtherBindings;
private final OnBindingEditDialogListener mListener;
private final ArrayList<Pair<String, ArrayList<Property>>> mProperties;
private Property mSelectedProperty;
private Button mTargetButton;
private EditText mFormulaEditText;
private Button mEditButton;
private Button mOkButton;
private OnBindingEditDialogListener mListener;
private ArrayList<Pair<String,ArrayList<Property>>> mProperties;
public BindingEditDialog(Context context, Binding init_value, ItemView itemView, OnBindingEditDialogListener listener) {
super(context);
@ -89,15 +86,15 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
// build the list of available properties minus the one already used
Class<? extends Item> itemClass = item.getClass();
List<Pair<String, Property[]>> all_properties = Arrays.asList(Property.getForItemClass(itemClass));
Pair<String, Property[]>[] all_properties = Property.getForItemClass(itemClass);
mProperties = new ArrayList<>();
for(Pair<String,Property[]> pair_from : all_properties) {
for (Pair<String, Property[]> pair_from : all_properties) {
ArrayList<Property> available_properties = new ArrayList<>();
Pair<String,ArrayList<Property>> pair_to = new Pair<>(pair_from.first, available_properties);
Pair<String, ArrayList<Property>> pair_to = new Pair<>(pair_from.first, available_properties);
for(Property p : pair_from.second) {
if(!isPropertyUsed(p.getName())) {
for (Property p : pair_from.second) {
if (!isPropertyUsed(p.getName())) {
available_properties.add(p);
}
}
@ -105,11 +102,11 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
mProperties.add(pair_to);
}
if(itemView.getClass() == ShortcutView.class) {
if (itemView.getClass() == ShortcutView.class) {
IconLabelView il = ((ShortcutView) itemView).getIconLabelView();
if(il != null) {
if (il != null) {
IconView iv = il.getIconView();
if(iv != null) {
if (iv != null) {
addSvgProperties(R.string.svg_icon, "svg/icon/", mProperties, iv.getSharedAsyncGraphicsDrawable());
}
}
@ -132,13 +129,13 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
}
private void addSvgProperties(int nameRes, String prefix, List<Pair<String, ArrayList<Property>>> all_properties, Drawable drawable) {
if(!(drawable instanceof SharedAsyncGraphicsDrawable)) {
if (!(drawable instanceof SharedAsyncGraphicsDrawable)) {
return;
}
SharedAsyncGraphicsDrawable sd = (SharedAsyncGraphicsDrawable) drawable;
if(sd.getType() != SharedAsyncGraphicsDrawable.TYPE_SVG) {
if (sd.getType() != SharedAsyncGraphicsDrawable.TYPE_SVG) {
return;
}
@ -146,7 +143,7 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
String name = getContext().getString(nameRes);
ArrayList<Property> properties = new ArrayList<>();
Pair<String,ArrayList<Property>> pair = new Pair<>(name, properties);
Pair<String, ArrayList<Property>> pair = new Pair<>(name, properties);
addSvgPropertiesForElement(prefix, svgDrawable.getSvgRoot(), properties);
@ -157,27 +154,27 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
}
});
if(properties.size() > 0) {
if (properties.size() > 0) {
all_properties.add(pair);
}
}
private void addSvgPropertiesForElement(String prefix, SvgElement element, ArrayList<Property> properties) {
String id = element.getId();
if(element instanceof SvgGroup) {
for(SvgElement child : ((SvgGroup)element).getChildren()) {
if (element instanceof SvgGroup) {
for (SvgElement child : ((SvgGroup) element).getChildren()) {
addSvgPropertiesForElement(prefix, child, properties);
}
}
if(id != null) {
if (id != null) {
Context context = getContext();
if(element instanceof SvgPath) {
properties.add(new Property(context.getString(R.string.svgp_path, id), prefix+id+"/path", Property.TYPE_STRING));
properties.add(new Property(context.getString(R.string.svgp_style, id), prefix+id+"/style", Property.TYPE_STRING));
properties.add(new Property(context.getString(R.string.svgp_transform, id), prefix+id+"/transform", Property.TYPE_STRING));
} else if(element instanceof SvgGroup) {
properties.add(new Property(context.getString(R.string.svgp_transform, id), prefix+id+"/transform", Property.TYPE_STRING));
if (element instanceof SvgPath) {
properties.add(new Property(context.getString(R.string.svgp_path, id), prefix + id + "/path", Property.TYPE_STRING));
properties.add(new Property(context.getString(R.string.svgp_style, id), prefix + id + "/style", Property.TYPE_STRING));
properties.add(new Property(context.getString(R.string.svgp_transform, id), prefix + id + "/transform", Property.TYPE_STRING));
} else if (element instanceof SvgGroup) {
properties.add(new Property(context.getString(R.string.svgp_transform, id), prefix + id + "/transform", Property.TYPE_STRING));
}
}
}
@ -186,26 +183,26 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
protected void onCreate(Bundle savedInstanceState) {
View view = getLayoutInflater().inflate(R.layout.ll_pref_binding_dialog, null);
((TextView)view.findViewById(R.id.bd_tt)).setText(R.string.bd_p);
((TextView)view.findViewById(R.id.bd_tf)).setText(R.string.bd_v);
((TextView) view.findViewById(R.id.bd_tt)).setText(R.string.bd_p);
((TextView) view.findViewById(R.id.bd_tf)).setText(R.string.bd_v);
mTargetButton = (Button) view.findViewById(R.id.bd_t);
mTargetButton = view.findViewById(R.id.bd_t);
mSelectedProperty = mInitValue == null ? null : Property.getByName(mInitValue.target);
mTargetButton.setText(mSelectedProperty == null ? getContext().getString(R.string.bd_s) : mSelectedProperty.getLabel());
mTargetButton.setEnabled(mInitValue == null);
mTargetButton.setOnClickListener(this);
Button builtin = (Button) view.findViewById(R.id.bd_fb);
Button builtin = view.findViewById(R.id.bd_fb);
builtin.setTypeface(LLApp.get().getIconsTypeface());
builtin.setOnClickListener(this);
mEditButton = (Button) view.findViewById(R.id.bd_fe);
mEditButton = view.findViewById(R.id.bd_fe);
mEditButton.setTypeface(LLApp.get().getIconsTypeface());
mEditButton.setOnClickListener(this);
mEditButton.setEnabled(mInitValue != null);
mFormulaEditText = (EditText) view.findViewById(R.id.bd_f);
if(mInitValue != null) {
mFormulaEditText = view.findViewById(R.id.bd_f);
if (mInitValue != null) {
mFormulaEditText.setText(mInitValue.formula);
}
@ -248,14 +245,15 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
}
private void save(boolean open_in_script_editor) {
String target =mSelectedProperty.getName();
String target = mSelectedProperty.getName();
String formula = mFormulaEditText.getText().toString();
Binding binding = new Binding(target, formula, mInitValue==null ? true : mInitValue.enabled);
Binding binding = new Binding(target, formula, mInitValue == null || mInitValue.enabled);
mListener.onBindingEdited(binding, open_in_script_editor);
}
private static final String ROOT_KEY = "r";
private static final String CHILD_KEY = "c";
public interface OnBindingEditDialogListener {
void onBindingEdited(Binding binding, boolean open_in_script_editor);
}
private class PropertySelectionDialog extends Dialog implements ExpandableListView.OnChildClickListener {
@ -273,13 +271,13 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
List<Map<String, String>> groupData = new ArrayList<>();
List<List<Map<String, String>>> childData = new ArrayList<>();
for(Pair<String,ArrayList<Property>> category : mProperties) {
for (Pair<String, ArrayList<Property>> category : mProperties) {
HashMap<String, String> value = new HashMap<>();
value.put(ROOT_KEY, category.first);
groupData.add(value);
List<Map<String, String>> child_values = new ArrayList<>();
for(Property p : category.second) {
for (Property p : category.second) {
HashMap<String, String> child_value = new HashMap<>();
child_value.put(CHILD_KEY, p.getLabel());
child_values.add(child_value);
@ -292,13 +290,13 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
groupData,
android.R.layout.simple_expandable_list_item_1,
new String[] { ROOT_KEY },
new int[] { android.R.id.text1 },
new String[]{ROOT_KEY},
new int[]{android.R.id.text1},
childData,
android.R.layout.simple_expandable_list_item_1,
new String[] { CHILD_KEY },
new int[] { android.R.id.text1 }
new String[]{CHILD_KEY},
new int[]{android.R.id.text1}
);
list.setAdapter(adapter);
@ -319,7 +317,7 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
private class VariableSelectionDialog extends Dialog implements ExpandableListView.OnChildClickListener {
private SimpleExpandableListAdapter mAdapter;
private Pair<String,BuiltinVariable[]>[] mBuiltinVariables;
private Pair<String, BuiltinVariable[]>[] mBuiltinVariables;
private ArrayList<Variable> mUserVariables;
public VariableSelectionDialog(Context context) {
@ -343,13 +341,13 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
List<Map<String, String>> groupData = new ArrayList<>();
List<List<Map<String, String>>> childData = new ArrayList<>();
for(Pair<String,BuiltinVariable[]> category : mBuiltinVariables) {
for (Pair<String, BuiltinVariable[]> category : mBuiltinVariables) {
HashMap<String, String> value = new HashMap<>();
value.put(ROOT_KEY, category.first);
groupData.add(value);
List<Map<String, String>> child_values = new ArrayList<>();
for(BuiltinVariable bv : category.second) {
for (BuiltinVariable bv : category.second) {
HashMap<String, String> child_value = new HashMap<>();
child_value.put(CHILD_KEY, bv.label);
child_values.add(child_value);
@ -362,7 +360,7 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
groupData.add(value);
List<Map<String, String>> child_values = new ArrayList<>();
for(Variable v : mUserVariables) {
for (Variable v : mUserVariables) {
HashMap<String, String> child_value = new HashMap<>();
child_value.put(CHILD_KEY, v.name);
child_values.add(child_value);
@ -370,19 +368,18 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
childData.add(child_values);
mAdapter = new SimpleExpandableListAdapter(
getContext(),
groupData,
android.R.layout.simple_expandable_list_item_1,
new String[] { ROOT_KEY },
new int[] { android.R.id.text1 },
new String[]{ROOT_KEY},
new int[]{android.R.id.text1},
childData,
android.R.layout.simple_expandable_list_item_1,
new String[] { CHILD_KEY },
new int[] { android.R.id.text1 }
new String[]{CHILD_KEY},
new int[]{android.R.id.text1}
);
list.setAdapter(mAdapter);
@ -393,14 +390,14 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
String name;
if(groupPosition < mBuiltinVariables.length) {
if (groupPosition < mBuiltinVariables.length) {
name = mBuiltinVariables[groupPosition].second[childPosition].name;
} else {
name = mUserVariables.get(childPosition).name;
}
int selstart = mFormulaEditText.getSelectionStart();
int selend = mFormulaEditText.getSelectionEnd();
mFormulaEditText.getText().replace(Math.min(selstart,selend), Math.max(selstart, selend), "$"+name);
mFormulaEditText.getText().replace(Math.min(selstart, selend), Math.max(selstart, selend), "$" + name);
dismiss();
return true;
}

View file

@ -26,11 +26,16 @@ package net.pierrox.lightning_launcher.util;
import android.app.ActivityManager;
import android.app.Service;
import android.content.*;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.telephony.TelephonyManager;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.activities.Dashboard;
import net.pierrox.lightning_launcher.activities.LockScreen;
@ -41,15 +46,16 @@ import java.util.List;
public class EmptyService extends Service {
private BroadcastReceiver mBroadcastReceiver=new BroadcastReceiver() {
private static final int MODE_CHECK_ON_TOP = 0;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
boolean launched = false;
if(LockScreen.sThis==null && LLApp.get().getAppEngine().getGlobalConfig().lockScreen != Page.NONE) {
if (LockScreen.sThis == null && LLApp.get().getAppEngine().getGlobalConfig().lockScreen != Page.NONE) {
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if(tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
Intent locked = new Intent(Dashboard.BROADCAST_ACTION_LOCKED);
sendBroadcast(locked);
@ -60,12 +66,12 @@ public class EmptyService extends Service {
}
}
if((launched || LockScreen.sThis!=null) && mMoveTaskToFront != null) {
if ((launched || LockScreen.sThis != null) && mMoveTaskToFront != null) {
mMode = MODE_CHECK_ON_TOP;
mHandler.postDelayed(mCheckOnTop, 3000);
}
} else if(LockScreen.sMyTaskId != null && action.equals(Intent.ACTION_SCREEN_ON)) {
if(mMoveTaskToFront != null) {
} else if (LockScreen.sMyTaskId != null && action.equals(Intent.ACTION_SCREEN_ON)) {
if (mMoveTaskToFront != null) {
mHandler.removeCallbacks(mCheckOnTop);
}
@ -110,21 +116,18 @@ public class EmptyService extends Service {
}
}
};
@Override
public IBinder onBind(Intent arg0) {
return null;
}
private static final int MODE_MOVE_ON_TOP_PENDING = 1;
private ActivityManager mActivityManager;
private Method mMoveTaskToFront;
private ComponentName mLockScreenComponenentName;
private Handler mHandler;
private static final int MODE_CHECK_ON_TOP = 0;
private static final int MODE_MOVE_ON_TOP_PENDING = 1;
private int mMode;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
@ -138,10 +141,10 @@ public class EmptyService extends Service {
mMoveTaskToFront = null;
}
if(Build.VERSION.SDK_INT>=8) {
IntentFilter intent_filter=new IntentFilter();
if (Build.VERSION.SDK_INT >= 8) {
IntentFilter intent_filter = new IntentFilter();
intent_filter.addAction(Intent.ACTION_SCREEN_OFF);
if(mMoveTaskToFront != null) {
if (mMoveTaskToFront != null) {
intent_filter.addAction(Intent.ACTION_SCREEN_ON);
}
registerReceiver(mBroadcastReceiver, intent_filter);
@ -156,13 +159,13 @@ public class EmptyService extends Service {
}
private Runnable mCheckOnTop = new Runnable() {
private final Runnable mCheckOnTop = new Runnable() {
@Override
public void run() {
if(mMode == MODE_CHECK_ON_TOP) {
if(LockScreen.sThis != null) {
if (mMode == MODE_CHECK_ON_TOP) {
if (LockScreen.sThis != null) {
List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
if(mLockScreenComponenentName.compareTo(tasks.get(0).topActivity) != 0) {
if (mLockScreenComponenentName.compareTo(tasks.get(0).topActivity) != 0) {
mMode = MODE_MOVE_ON_TOP_PENDING;
mHandler.postDelayed(mCheckOnTop, 22000);
} else {
@ -170,10 +173,10 @@ public class EmptyService extends Service {
}
}
} else {
if(LockScreen.sThis != null) {
if (LockScreen.sThis != null) {
try {
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if(tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
mMoveTaskToFront.invoke(mActivityManager, LockScreen.sMyTaskId, 0);
}
mMode = MODE_CHECK_ON_TOP;

View file

@ -60,44 +60,22 @@ import java.util.HashMap;
import java.util.List;
public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogInterface.OnClickListener, View.OnClickListener, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
public interface FileAndDirectoryPickerDialogListener {
void onFileSelected(File file, File newDirectory);
}
private boolean mForDirectory;
private boolean mForFont;
private boolean mMergeSingleDirectories;
private ScriptManager mScriptManager;
private File mRootDirectory;
private FileAndDirectoryPickerDialogListener mListener;
private static final String FONT_ITEM_PREVIEW = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private final boolean mForDirectory;
private final boolean mForFont;
private final boolean mMergeSingleDirectories;
private final ScriptManager mScriptManager;
private final File mRootDirectory;
private final FileAndDirectoryPickerDialogListener mListener;
private final String[] mExtensions;
private final Bitmap mDirectoryIcon;
private final Bitmap mFileIcon;
private Button mUpButton;
private ListView mFileListView;
private TextView mCurrentPathView;
private TextView mEmptyView;
private File mCurrentDirectory;
private FileFilter mFileFilter;
private String[] mExtensions;
private Bitmap mDirectoryIcon;
private Bitmap mFileIcon;
public static void showForFont(Context context, File initialDirectory, FileAndDirectoryPickerDialogListener listener) {
String[] ttfExtensions = {".ttf", ".otf"};
File rootDirectory = new File("/");
if(initialDirectory == null) {
initialDirectory = Environment.getExternalStorageDirectory();
}
new FileAndDirectoryPickerDialog(context, false, true, initialDirectory, rootDirectory, ttfExtensions, null, listener).show();
}
public static void showForScriptDirectory(Context context, File initialDirectory, ScriptManager scriptManager, FileAndDirectoryPickerDialogListener listener) {
File rootDirectory = scriptManager.getScriptsDir();
if(initialDirectory == null) {
initialDirectory = rootDirectory;
}
new FileAndDirectoryPickerDialog(context, true, false, initialDirectory, rootDirectory, null, scriptManager, listener).show();
}
private FileAndDirectoryPickerDialog(Context context, boolean forDirectory, boolean forFont, File initialDirectory, File rootDirectory, String[] extensions, ScriptManager scriptManager, FileAndDirectoryPickerDialogListener listener) {
super(context);
@ -118,7 +96,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
mDirectoryIcon = Utils.createIconFromText(size, ".", fgColor);
mFileIcon = Utils.createIconFromText(size, "/", fgColor);
if(mForDirectory) {
if (mForDirectory) {
// mFileFilter = new FileFilter() {
// @Override
// public boolean accept(File pathname) {
@ -140,27 +118,44 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
}
}
public static void showForFont(Context context, File initialDirectory, FileAndDirectoryPickerDialogListener listener) {
String[] ttfExtensions = {".ttf", ".otf"};
File rootDirectory = new File("/");
if (initialDirectory == null) {
initialDirectory = Environment.getExternalStorageDirectory();
}
new FileAndDirectoryPickerDialog(context, false, true, initialDirectory, rootDirectory, ttfExtensions, null, listener).show();
}
public static void showForScriptDirectory(Context context, File initialDirectory, ScriptManager scriptManager, FileAndDirectoryPickerDialogListener listener) {
File rootDirectory = scriptManager.getScriptsDir();
if (initialDirectory == null) {
initialDirectory = rootDirectory;
}
new FileAndDirectoryPickerDialog(context, true, false, initialDirectory, rootDirectory, null, scriptManager, listener).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
View view = getLayoutInflater().inflate(R.layout.file_dir_picker_dialog, null);
setView(view);
mUpButton = (Button) view.findViewById(R.id.up);
mUpButton = view.findViewById(R.id.up);
mUpButton.setText(R.string.file_picker_activity_up);
mUpButton.setOnClickListener(this);
mCurrentPathView = (TextView) view.findViewById(R.id.path);
mCurrentPathView = view.findViewById(R.id.path);
mFileListView = (ListView) view.findViewById(android.R.id.list);
mFileListView = view.findViewById(android.R.id.list);
mFileListView.setOnItemClickListener(this);
mFileListView.setOnItemLongClickListener(this);
mEmptyView = (TextView) view.findViewById(R.id.empty);
mEmptyView = view.findViewById(R.id.empty);
mEmptyView.setText(R.string.nfh);
setButton(BUTTON_NEGATIVE, getContext().getString(android.R.string.cancel), this);
if(mForDirectory) {
if (mForDirectory) {
setButton(BUTTON_POSITIVE, getContext().getString(android.R.string.ok), this);
}
@ -169,7 +164,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
super.onCreate(savedInstanceState);
getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
ViewGroup content = (ViewGroup) getWindow().findViewById(android.R.id.content);
ViewGroup content = getWindow().findViewById(android.R.id.content);
View child = content.getChildAt(0);
child.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
child.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
@ -182,7 +177,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == BUTTON_POSITIVE) {
if (which == BUTTON_POSITIVE) {
mListener.onFileSelected(mCurrentDirectory, mCurrentDirectory);
dismiss();
}
@ -190,18 +185,18 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
@Override
public void onClick(View v) {
if(v.getId() == R.id.up) {
if (v.getId() == R.id.up) {
// remove symlinks to ensure that it's not possible to go back elsewhere
String canonicalCurrent, canonicalRoot;
try {
canonicalCurrent = mCurrentDirectory.getCanonicalPath();
canonicalRoot = mRootDirectory.getCanonicalPath();
} catch(IOException e) {
} catch (IOException e) {
canonicalCurrent = "";
canonicalRoot = "";
}
if(mMergeSingleDirectories) {
if (mMergeSingleDirectories) {
while (!canonicalCurrent.equals(canonicalRoot)) {
File parent = mCurrentDirectory.getParentFile();
if (parent != null) {
@ -220,9 +215,9 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
}
} else {
if(!canonicalCurrent.equals(canonicalRoot)) {
if (!canonicalCurrent.equals(canonicalRoot)) {
File parent = mCurrentDirectory.getParentFile();
if(parent != null) {
if (parent != null) {
gotoDirectory(parent);
}
}
@ -233,10 +228,10 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
File file = (File) mFileListView.getAdapter().getItem(position);
if(file.isDirectory()) {
if (file.isDirectory()) {
gotoDirectory(file);
} else {
if(!mForDirectory) {
if (!mForDirectory) {
mListener.onFileSelected(file, mCurrentDirectory);
dismiss();
}
@ -246,8 +241,8 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
File file = (File) mFileListView.getAdapter().getItem(i);
if(!file.isDirectory()) {
if(mForFont) {
if (!file.isDirectory()) {
if (mForFont) {
showDeleteFontDialog(file);
} else {
showDeleteFileDialog(file);
@ -259,7 +254,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
}
private void showDeleteFileDialog(final File file) {
AlertDialog.Builder builder=new AlertDialog.Builder(getContext());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(R.string.delete_file);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
@ -291,12 +286,12 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
}
private boolean matchExtension(String name) {
if(mExtensions == null) {
if (mExtensions == null) {
return true;
}
String lname = name.toLowerCase();
for(String e : mExtensions) {
if(lname.endsWith(e)) {
for (String e : mExtensions) {
if (lname.endsWith(e)) {
return true;
}
}
@ -307,13 +302,13 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
mCurrentDirectory = dir;
File[] files = mCurrentDirectory.listFiles(mFileFilter);
if(files != null) {
if(mMergeSingleDirectories) {
for (int n=files.length-1; n>=0; n--) {
if (files != null) {
if (mMergeSingleDirectories) {
for (int n = files.length - 1; n >= 0; n--) {
File d = files[n];
for(;;) {
for (; ; ) {
File[] subDirs = d.listFiles();
if(subDirs != null && subDirs.length == 1 && subDirs[0].isDirectory()) {
if (subDirs != null && subDirs.length == 1 && subDirs[0].isDirectory()) {
d = subDirs[0];
} else {
break;
@ -326,8 +321,8 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File arg0, File arg1) {
if(arg0.isDirectory() && !arg1.isDirectory()) return -1;
if(arg1.isDirectory() && !arg0.isDirectory()) return 1;
if (arg0.isDirectory() && !arg1.isDirectory()) return -1;
if (arg1.isDirectory() && !arg0.isDirectory()) return 1;
return arg0.getName().compareTo(arg1.getName());
}
});
@ -338,14 +333,14 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
mFileListView.setAdapter(new FileAdapter(getContext(), items));
String rootPath = mRootDirectory.getAbsolutePath();
if(!rootPath.endsWith("/")) {
if (!rootPath.endsWith("/")) {
rootPath += "/";
}
String currentPath = mCurrentDirectory.getAbsolutePath();
if(!currentPath.endsWith("/")) {
if (!currentPath.endsWith("/")) {
currentPath += "/";
}
String path = "/" + currentPath.substring(rootPath.length(), currentPath.length());
String path = "/" + currentPath.substring(rootPath.length());
/*
/ / -> /
@ -354,12 +349,15 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
/scripts/a -> /a
*/
mCurrentPathView.setText(path);
mEmptyView.setVisibility(files.length==0 ? View.VISIBLE : View.GONE);
mEmptyView.setVisibility(files.length == 0 ? View.VISIBLE : View.GONE);
}
public interface FileAndDirectoryPickerDialogListener {
void onFileSelected(File file, File newDirectory);
}
private static final String FONT_ITEM_PREVIEW = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private class FileAdapter extends ArrayAdapter<File> {
private HashMap<File,Typeface> mTypefaces = new HashMap<>();
private final HashMap<File, Typeface> mTypefaces = new HashMap<>();
public FileAdapter(Context context, List<File> objects) {
super(context, 0, objects);
@ -367,26 +365,26 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.two_lines_list_item, null);
}
File f = getItem(position);
CheckedTextView line1 = (CheckedTextView) convertView.findViewById(android.R.id.text1);
TextView line2 = (TextView) convertView.findViewById(android.R.id.text2);
CheckedTextView line1 = convertView.findViewById(android.R.id.text1);
TextView line2 = convertView.findViewById(android.R.id.text2);
String text1, text2 = null;
Typeface typeface = Typeface.DEFAULT;
String name = f.getName();
if(f.isDirectory()) {
if (f.isDirectory()) {
int length = mCurrentDirectory.getAbsolutePath().length();
if(length > 1) {
if (length > 1) {
// different from "/"
length++;
}
text1 = f.getAbsolutePath().substring(length);
Utils.setEnabledStateOnViews(convertView, true);
} else {
if(mScriptManager != null) {
if (mScriptManager != null) {
text1 = null;
try {
int id = Integer.parseInt(name);
@ -395,7 +393,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
} catch (NumberFormatException e) {
// pass
}
if(text1 == null) {
if (text1 == null) {
text1 = name;
}
} else {
@ -418,7 +416,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
}
Utils.setEnabledStateOnViews(convertView, !mForDirectory);
}
if(text2 == null) {
if (text2 == null) {
line2.setVisibility(View.GONE);
} else {
line2.setVisibility(View.VISIBLE);
@ -427,7 +425,7 @@ public class FileAndDirectoryPickerDialog extends AlertDialog implements DialogI
}
line1.setText(text1);
((ImageView)convertView.findViewById(android.R.id.icon)).setImageBitmap(f.isDirectory() ? mDirectoryIcon : mFileIcon);
((ImageView) convertView.findViewById(android.R.id.icon)).setImageBitmap(f.isDirectory() ? mDirectoryIcon : mFileIcon);
return convertView;

View file

@ -42,107 +42,36 @@ import java.util.Map;
*/
public class Indentation {
private static final int INDENT_SIZE = 2;
private Map<EditText, IndentationTextWatcher> mRegistered = new HashMap<>();
/**
* Registers the AutoIndentation on the provided editText (unless it was already registered)
*/
public void register(EditText editText){
if(mRegistered.containsKey(editText))
return;
IndentationTextWatcher itw = new IndentationTextWatcher(editText);
editText.addTextChangedListener(itw);
mRegistered.put(editText, itw);
}
/**
* Unregisters the AutoIndentation on the provided editText (if it was registered before)
*/
public void unregister(EditText editText){
if(!mRegistered.containsKey(editText))
return;
editText.removeTextChangedListener(mRegistered.get(editText));
mRegistered.remove(editText);
}
/**
* Called when an ending bracket is inserted. Decreases the indentation.
* @param posBracket where the endbracket was
* @param editable where to unindent
*/
private void onEndBracket(int posBracket, Editable editable){
// check if beginning of line
if( posBracket == getLineIndent(posBracket, editable).second ){
// decrease indent
decreaseIndent( posBracket, editable );
}
}
/**
* Called when a newline is inserted. Indents it with the same indentation as the previous line (if any)
* @param posEnter position of the newline char
* @param editable where to indent
*/
private void onNewLine(int posEnter, Editable editable){
int n = getLineIndent(posEnter, editable).first;
StringBuilder indent = new StringBuilder();
for(int i=0;i<n;++i){
indent.append(" ");
}
// do if previous line ends in open bracket
if(posEnter > 0 && editable.charAt(posEnter - 1) == '{'){
// add newline if also following close bracket
if(posEnter < editable.length() - 1 && editable.charAt(posEnter + 1) == '}'){
editable.insert(posEnter + 2, "\n" + indent.toString() + "}");
// this avoids moving the cursor
editable.replace(posEnter + 1, posEnter + 2, "");
}
// add indent size
for(int i=0;i<INDENT_SIZE;++i){
indent.append(" ");
}
}
// write indent
editable.insert(posEnter + 1, indent.toString());
}
// ------------ functions -----------------
private final Map<EditText, IndentationTextWatcher> mRegistered = new HashMap<>();
/**
* Returns the size of the indent in the current line (spaces at the left) and the position of the first non-space char
*
* @param currentpos pos of current line (any char)
* @param editable where to search
* @param editable where to search
* @return length of indent (number of spaces) and position of first non-space char (can be end of file)
*/
private static Pair<Integer, Integer> getLineIndent(int currentpos, Editable editable){
private static Pair<Integer, Integer> getLineIndent(int currentpos, Editable editable) {
// goto beginning of line
if(currentpos != 0) {
do{
if (currentpos != 0) {
do {
currentpos--;
}while (currentpos >= 0 && editable.charAt(currentpos) != '\n');
} while (currentpos >= 0 && editable.charAt(currentpos) != '\n');
currentpos++;
}
// find indent size
int n = 0;
boolean cont = true;
while(cont && currentpos < editable.length()){
switch (editable.charAt(currentpos)){
while (cont && currentpos < editable.length()) {
switch (editable.charAt(currentpos)) {
case ' ':
n++;
currentpos++;
break;
case '\t':
n+=INDENT_SIZE;
n += INDENT_SIZE;
currentpos++;
break;
//case '\n':
@ -152,69 +81,72 @@ public class Indentation {
}
return new Pair<>(n, currentpos);
}
/**
* Changes the indentation of all the lines selected
* @param posLeft start of selection
*
* @param posLeft start of selection
* @param posRight end of selection
* @param increase if true increase indent, decrease otherwise
* @param editable where to apply the indentation
* @return the new selection (may have changed due to the indentation changes)
*/
public static Pair<Integer, Integer> modifyIndent(int posLeft, int posRight, boolean increase, Editable editable){
public static Pair<Integer, Integer> modifyIndent(int posLeft, int posRight, boolean increase, Editable editable) {
String span = "modifyIntent";
editable.setSpan(span, posLeft, posRight, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
Deque<Integer> positions = new ArrayDeque<>();
while(posLeft <= posRight && posLeft <= editable.length()){
while (posLeft <= posRight && posLeft <= editable.length()) {
// mark position to indent
positions.push(posLeft);
// find next line (next newline char)
posLeft++;
while(posLeft <= posRight && posLeft <= editable.length() && editable.charAt(posLeft - 1) != '\n')
while (posLeft <= posRight && posLeft <= editable.length() && editable.charAt(posLeft - 1) != '\n')
posLeft++;
}
for (Integer position : positions) {
// indent the lines in reverse order
if(increase)
if (increase)
increaseIndent(position, editable);
else
decreaseIndent(position, editable);
}
//restore span
return new Pair<>(editable.getSpanStart(span), editable.getSpanEnd(span));
}
/**
* Increases the indentation of a single line
*
* @param posCursor position of a character in the line that will be indented
* @param editable where to apply the indentation
* @param editable where to apply the indentation
*/
private static void increaseIndent(int posCursor, Editable editable){
private static void increaseIndent(int posCursor, Editable editable) {
Pair<Integer, Integer> n_beg = getLineIndent(posCursor, editable);
int beg = n_beg.second;
// increase indent adding spaces
for(int i=0; i< INDENT_SIZE; i++) editable.insert(beg, " ");
for (int i = 0; i < INDENT_SIZE; i++) editable.insert(beg, " ");
}
/**
* Decreases the indentation of a single line
*
* @param posCursor position of a character in the line that will be indented
* @param editable where to apply the indentation
* @param editable where to apply the indentation
*/
private static void decreaseIndent(int posCursor, Editable editable){
private static void decreaseIndent(int posCursor, Editable editable) {
Pair<Integer, Integer> n_beg = getLineIndent(posCursor, editable);
int n = n_beg.first;
int beg = n_beg.second;
if ( n >= INDENT_SIZE ){
if (n >= INDENT_SIZE) {
// enough intent to remove, remove the first tab, or all the spaces if no tabs found
int p = 1;
while (p <= INDENT_SIZE) {
@ -227,61 +159,134 @@ public class Indentation {
}
// no tabs found, only spaces, remove them
editable.delete(beg - INDENT_SIZE, beg);
}else{
} else {
// not enough indent (so no tabs), just remove all the previous spaces
editable.delete(beg - n, beg);
}
}
// ------------ functions -----------------
/**
* Registers the AutoIndentation on the provided editText (unless it was already registered)
*/
public void register(EditText editText) {
if (mRegistered.containsKey(editText))
return;
IndentationTextWatcher itw = new IndentationTextWatcher(editText);
editText.addTextChangedListener(itw);
mRegistered.put(editText, itw);
}
/**
* Unregisters the AutoIndentation on the provided editText (if it was registered before)
*/
public void unregister(EditText editText) {
if (!mRegistered.containsKey(editText))
return;
editText.removeTextChangedListener(mRegistered.get(editText));
mRegistered.remove(editText);
}
/**
* Called when an ending bracket is inserted. Decreases the indentation.
*
* @param posBracket where the endbracket was
* @param editable where to unindent
*/
private void onEndBracket(int posBracket, Editable editable) {
// check if beginning of line
if (posBracket == getLineIndent(posBracket, editable).second) {
// decrease indent
decreaseIndent(posBracket, editable);
}
}
/**
* Called when a newline is inserted. Indents it with the same indentation as the previous line (if any)
*
* @param posEnter position of the newline char
* @param editable where to indent
*/
private void onNewLine(int posEnter, Editable editable) {
int n = getLineIndent(posEnter, editable).first;
StringBuilder indent = new StringBuilder();
for (int i = 0; i < n; ++i) {
indent.append(" ");
}
// do if previous line ends in open bracket
if (posEnter > 0 && editable.charAt(posEnter - 1) == '{') {
// add newline if also following close bracket
if (posEnter < editable.length() - 1 && editable.charAt(posEnter + 1) == '}') {
editable.insert(posEnter + 2, "\n" + indent + "}");
// this avoids moving the cursor
editable.replace(posEnter + 1, posEnter + 2, "");
}
// add indent size
for (int i = 0; i < INDENT_SIZE; ++i) {
indent.append(" ");
}
}
// write indent
editable.insert(posEnter + 1, indent.toString());
}
// ------------ textwatcher ----------------
private class IndentationTextWatcher implements TextWatcher {
private final String mSpanNewline = "mSpanNewline";
private final String mSpanEndBracket = "mSpanEndBracket";
private final EditText mEditText;
private boolean mEditing = false;
IndentationTextWatcher(EditText mEditText) {
this.mEditText = mEditText;
}
private String mSpanNewline = "mSpanNewline";
private String mSpanEndBracket = "mSpanEndBracket";
private boolean mEditing = false;
private EditText mEditText;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(mEditing) return;
if(count == 1 && s.charAt(start) == '\n'){
if (mEditing) return;
if (count == 1 && s.charAt(start) == '\n') {
// newline inserted
mEditText.getEditableText().setSpan(mSpanNewline,start,start,0);
mEditText.getEditableText().setSpan(mSpanNewline, start, start, 0);
}
if(count == 1 && s.charAt(start) == '}'){
if (count == 1 && s.charAt(start) == '}') {
// end bracket inserted
mEditText.getEditableText().setSpan(mSpanEndBracket, start, start, 0);
}
}
@Override
public void afterTextChanged(Editable editable) {
mEditing = true;
int spanPos;
// check newline
spanPos = editable.getSpanStart(mSpanNewline);
editable.removeSpan(mSpanNewline);
if (spanPos != -1 && editable.charAt(spanPos) == '\n')
onNewLine(spanPos, editable);
// check endbracket
spanPos = editable.getSpanStart(mSpanEndBracket);
editable.removeSpan(mSpanEndBracket);
if (spanPos != -1 && editable.charAt(spanPos) == '}')
onEndBracket(spanPos, editable);
mEditing = false;
}
}

View file

@ -72,7 +72,7 @@ public class LightningLWPService extends WallpaperService {
@Override
public final Resources getResources() {
if(mResourcesWrapperHelper == null) {
if (mResourcesWrapperHelper == null) {
mResourcesWrapperHelper = new ResourcesWrapperHelper(this, super.getResources());
}
return mResourcesWrapperHelper.getResources();
@ -104,15 +104,15 @@ public class LightningLWPService extends WallpaperService {
LightningEngine lightningEngine = app.getAppEngine();
lightningEngine.registerGlobalConfigChangeListener(this);
final GlobalConfig globalConfig = lightningEngine.getGlobalConfig();
mLWPDesktopId =globalConfig.lwpScreen;
mLWPDesktopId = globalConfig.lwpScreen;
mScreen = new LightningLWPScreen(LightningLWPService.this, R.layout.lwp);
mContentView = (EventFrameLayout) mScreen.getContentView();
mItemLayout = (ItemLayout) mContentView.findViewById(R.id.lwp_il);
mItemLayout = mContentView.findViewById(R.id.lwp_il);
mScreen.takeItemLayoutOwnership(mItemLayout);
mNoDesktopView = (TextView) mContentView.findViewById(R.id.empty);
mNoDesktopView = mContentView.findViewById(R.id.empty);
mNoDesktopView.setText(R.string.sd);
mNoDesktopView.setOnClickListener(new View.OnClickListener() {
@Override
@ -125,14 +125,14 @@ public class LightningLWPService extends WallpaperService {
IBinder token = null;
final Field[] declaredFields = getClass().getSuperclass().getDeclaredFields();
for (Field f : declaredFields) {
if(f.getName().equals("mWindowToken")) {
if (f.getName().equals("mWindowToken")) {
f.setAccessible(true);
token = (IBinder) f.get(this);
break;
}
}
if(token != null) {
if (token != null) {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@ -184,7 +184,7 @@ public class LightningLWPService extends WallpaperService {
mScreen.setCustomScreenSize(width, height);
if(!mUseWindow) {
if (!mUseWindow) {
layout();
draw();
}
@ -192,7 +192,7 @@ public class LightningLWPService extends WallpaperService {
@Override
public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
if(!mUseWindow) {
if (!mUseWindow) {
draw();
}
}
@ -200,9 +200,9 @@ public class LightningLWPService extends WallpaperService {
@Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
Rect boundingBox = mItemLayout.getItemsBoundingBox();
float x = xOffset*(mItemLayout.getWidth()-boundingBox.width()) - boundingBox.left;
float y = yOffset*(mItemLayout.getHeight()-boundingBox.height()) - boundingBox.top;
if(mItemLayout.getCurrentX() != x || mItemLayout.getCurrentY() != y) {
float x = xOffset * (mItemLayout.getWidth() - boundingBox.width()) - boundingBox.left;
float y = yOffset * (mItemLayout.getHeight() - boundingBox.height()) - boundingBox.top;
if (mItemLayout.getCurrentX() != x || mItemLayout.getCurrentY() != y) {
mItemLayout.moveTo(x, y, 1);
}
}
@ -211,13 +211,13 @@ public class LightningLWPService extends WallpaperService {
public Bundle onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested) {
boolean isTap = WallpaperManager.COMMAND_TAP.equals(action);
boolean isSecondaryTap = WallpaperManager.COMMAND_SECONDARY_TAP.equals(action);
if((isTap || isSecondaryTap) && !mMainPage.config.lwpStdEvents) {
if ((isTap || isSecondaryTap) && !mMainPage.config.lwpStdEvents) {
int[] offset = new int[2];
mContentView.getLocationOnScreen(offset);
x -= offset[0];
y -= offset[1];
if(mUseWindow) {
if (mUseWindow) {
boolean dispatch = mContentView.getDispatchEvent();
mContentView.setDispatchEvent(true);
@ -229,11 +229,11 @@ public class LightningLWPService extends WallpaperService {
mContentView.dispatchTouchEvent(event);
mContentView.setDispatchEvent(dispatch);
} else if(mLWPDesktopId == Page.NONE){
} else if (mLWPDesktopId == Page.NONE) {
// preview mode, events won't perform click because the view needs to be attached to post click events, hence handle it manually
Rect r = new Rect();
mNoDesktopView.getHitRect(r);
if(r.contains(x, y)) {
if (r.contains(x, y)) {
startSettings();
}
}
@ -269,9 +269,9 @@ public class LightningLWPService extends WallpaperService {
}
private void setVisibility(boolean visible) {
if(visible != mVisible) {
if (visible != mVisible) {
mVisible = visible;
if(mVisible) {
if (mVisible) {
mScreen.resume();
} else {
mScreen.pause();
@ -280,7 +280,7 @@ public class LightningLWPService extends WallpaperService {
}
private void configurePage() {
if(!((LLAppExtreme)LLApp.get()).hasLWP()) {
if (!((LLAppExtreme) LLApp.get()).hasLWP()) {
mLWPDesktopId = Page.NONE;
}
boolean hasPage = mLWPDesktopId != Page.NONE;
@ -296,11 +296,11 @@ public class LightningLWPService extends WallpaperService {
@Override
public void onGlobalConfigChanged(GlobalConfig newGlobalConfig) {
if(newGlobalConfig.lwpScreen != mLWPDesktopId) {
if (newGlobalConfig.lwpScreen != mLWPDesktopId) {
mLWPDesktopId = newGlobalConfig.lwpScreen;
configurePage();
if(!mUseWindow) {
if (!mUseWindow) {
layout();
draw();
}
@ -324,7 +324,7 @@ public class LightningLWPService extends WallpaperService {
@Override
public void goToDesktopPosition(int page, float x, float y, float s, boolean animate, boolean absolute) {
if(Page.isDashboard(page) && page != getCurrentRootPage().id) {
if (Page.isDashboard(page) && page != getCurrentRootPage().id) {
LightningEngine engine = mMainPage.getEngine();
engine.getGlobalConfig().lwpScreen = page;
engine.notifyGlobalConfigChanged();
@ -340,7 +340,7 @@ public class LightningLWPService extends WallpaperService {
@Override
public ItemLayout loadRootItemLayout(int page, boolean reset_navigation_history, boolean displayImmediately, boolean animate) {
if(mItemLayout.getPage().id == page) {
if (mItemLayout.getPage().id == page) {
return mItemLayout;
} else {
return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate);
@ -380,7 +380,7 @@ public class LightningLWPService extends WallpaperService {
public void onPageModified(Page page) {
super.onPageModified(page);
if(page == mMainPage) {
if (page == mMainPage) {
mContentView.setDispatchEvent(page.config.lwpStdEvents);
}
}
@ -389,7 +389,7 @@ public class LightningLWPService extends WallpaperService {
public void setVisibility(boolean visible) {
int oldVisibility = mContentView.getVisibility();
int newVisibility = visible ? View.VISIBLE : View.GONE;
if(oldVisibility != newVisibility) {
if (oldVisibility != newVisibility) {
mContentView.setVisibility(newVisibility);
mContentView.startAnimation(AnimationUtils.loadAnimation(LightningLWPService.this, visible ? android.R.anim.fade_in : android.R.anim.fade_out));
}

View file

@ -40,40 +40,32 @@ import android.widget.Spinner;
import android.widget.TextView;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher_extreme.R;
import net.pierrox.lightning_launcher.activities.ScriptEditor;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher_extreme.R;
import java.io.File;
import java.util.ArrayList;
public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnItemSelectedListener {
private static boolean sShowSubDirs;
private static File sCurrentDirectory;
private final CheckBox mHasDataCheckBox;
private final EditText mDataTextView;
private final Spinner mTargetsSpinner;
private final Spinner mScriptSpinner;
private Button mSelectDirectoryButton;
private ArrayAdapter<Script> mScriptAdapter;
private ArrayList<Script> mAllScripts;
private final Button mSelectDirectoryButton;
private final ArrayAdapter<Script> mScriptAdapter;
private final ArrayList<Script> mAllScripts;
private final ScriptManager mScriptManager;
private final int mInitialTarget;
private final OnScriptPickerEvent mListener;
private Script mScript;
private int mInitialTarget;
private OnScriptPickerEvent mListener;
private static boolean sShowSubDirs;
private static File sCurrentDirectory;
public interface OnScriptPickerEvent {
public void onScriptPicked(String id_data, int target);
public void onScriptPickerCanceled();
}
public ScriptPickerDialog(final Context context, LightningEngine engine, String initial_id_data, final int initial_target, final OnScriptPickerEvent listener) {
super(context);
@ -82,36 +74,36 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
mListener = listener;
mScriptManager = engine.getScriptManager();
if(sCurrentDirectory == null) {
if (sCurrentDirectory == null) {
sCurrentDirectory = mScriptManager.getScriptsDir();
}
mAllScripts = mScriptManager.getAllScriptMatching(Script.FLAG_ALL);
setTitle(R.string.sst);
View content = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.dialog_select_script, null);
View content = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.dialog_select_script, null);
setView(content);
mScriptSpinner = (Spinner) content.findViewById(R.id.script);
mTargetsSpinner = (Spinner) content.findViewById(R.id.tg);
final Button sc_new = (Button) content.findViewById(R.id.sc_new);
mHasDataCheckBox = (CheckBox) content.findViewById(R.id.has_data);
mDataTextView = (EditText) content.findViewById(R.id.data);
((TextView)content.findViewById(R.id.tgt)).setText(R.string.tg);
((TextView)content.findViewById(R.id.sc_path)).setText(R.string.sc_path);
((TextView)content.findViewById(R.id.sc_name)).setText(R.string.sc_name);
mScriptSpinner = content.findViewById(R.id.script);
mTargetsSpinner = content.findViewById(R.id.tg);
final Button sc_new = content.findViewById(R.id.sc_new);
mHasDataCheckBox = content.findViewById(R.id.has_data);
mDataTextView = content.findViewById(R.id.data);
((TextView) content.findViewById(R.id.tgt)).setText(R.string.tg);
((TextView) content.findViewById(R.id.sc_path)).setText(R.string.sc_path);
((TextView) content.findViewById(R.id.sc_name)).setText(R.string.sc_name);
sc_new.setText(R.string.sc_new);
Button editButton = (Button) content.findViewById(R.id.edit);
Button editButton = content.findViewById(R.id.edit);
editButton.setTypeface(LLApp.get().getIconsTypeface());
editButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mScript != null) {
if (mScript != null) {
ScriptEditor.startActivity(context, mScript.id, 1);
}
}
});
mSelectDirectoryButton = (Button) content.findViewById(R.id.sc_d);
mSelectDirectoryButton = content.findViewById(R.id.sc_d);
mSelectDirectoryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -121,7 +113,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
sCurrentDirectory = file;
updateSelectDirectoryButton();
updateScriptsSpinner();
if(!mAllScripts.contains(mScript) && mAllScripts.size() > 0) {
if (!mAllScripts.contains(mScript) && mAllScripts.size() > 0) {
mScript = mAllScripts.get(0);
}
}
@ -130,7 +122,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
});
updateSelectDirectoryButton();
CheckBox showSubDirs = (CheckBox) content.findViewById(R.id.sc_sd);
CheckBox showSubDirs = content.findViewById(R.id.sc_sd);
showSubDirs.setText(R.string.sc_all);
showSubDirs.setChecked(sShowSubDirs);
showSubDirs.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@ -138,7 +130,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
sShowSubDirs = isChecked;
updateScriptsSpinner();
if(!mAllScripts.contains(mScript) && mAllScripts.size() > 0) {
if (!mAllScripts.contains(mScript) && mAllScripts.size() > 0) {
mScript = mAllScripts.get(0);
}
}
@ -167,7 +159,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
mScriptSpinner.requestFocus();
View targets_group = content.findViewById(R.id.tgg);
if(mInitialTarget == Script.TARGET_NONE) {
if (mInitialTarget == Script.TARGET_NONE) {
targets_group.setVisibility(View.GONE);
} else {
String[] target_names = new String[]{
@ -187,23 +179,23 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDataTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
if(isChecked) mDataTextView.requestFocus();
if (isChecked) mDataTextView.requestFocus();
else mDataTextView.clearFocus();
}
});
if(initial_id_data != null) {
if (initial_id_data != null) {
final Pair<Integer, String> pair = Script.decodeIdAndData(initial_id_data);
mScript = mScriptManager.getOrLoadScript(pair.first);
if(mScript != null) {
if (mScript != null) {
if (sShowSubDirs) {
File root = mScriptManager.getScriptsDir();
for(;;) {
for (; ; ) {
updateScriptsSpinner();
if(sCurrentDirectory.equals(root)) {
if (sCurrentDirectory.equals(root)) {
break;
}
if(mAllScripts.contains(mScript)) {
if (mAllScripts.contains(mScript)) {
break;
}
@ -275,18 +267,18 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
private void updateScriptsSpinner() {
ArrayList<Script> allScripts = mScriptManager.getAllScriptMatching(Script.FLAG_ALL);
String currentPath = mScriptManager.getRelativePath(sCurrentDirectory);
if(!currentPath.endsWith("/")) {
if (!currentPath.endsWith("/")) {
// ensure a trailing slash to avoid false match (like /ab and /ac whith current = /a)
currentPath += "/";
}
mAllScripts.clear();
for (Script script : allScripts) {
if(script.getType() == Script.TYPE_FILE) {
if (script.getType() == Script.TYPE_FILE) {
String relativePath = script.getRelativePath();
if(!relativePath.endsWith("/")) {
if (!relativePath.endsWith("/")) {
relativePath += "/";
}
if((sShowSubDirs && relativePath.startsWith(currentPath)) || relativePath.equals(currentPath)) {
if ((sShowSubDirs && relativePath.startsWith(currentPath)) || relativePath.equals(currentPath)) {
mAllScripts.add(script);
}
}
@ -295,7 +287,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
mScriptAdapter.notifyDataSetChanged();
int position = mAllScripts.indexOf(mScript);
if(position != -1) {
if (position != -1) {
mScriptSpinner.setSelection(position);
}
}
@ -303,4 +295,11 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
private void updateSelectDirectoryButton() {
mSelectDirectoryButton.setText(mScriptManager.getRelativePath(sCurrentDirectory));
}
public interface OnScriptPickerEvent {
void onScriptPicked(String id_data, int target);
void onScriptPickerCanceled();
}
}

View file

@ -43,110 +43,111 @@ import fr.xgouchet.texteditor.ui.AdvancedEditText;
* Class that Manages a searchable dialog (currently for the script editor).
*/
public class Search {
private Activity mCntx;
private AdvancedEditText mEditText;
private final Activity mCntx;
private final AdvancedEditText mEditText;
private AlertDialog mDialog;
private EditText mEdTxt;
private CheckBox mChkBackwards;
private CheckBox mChkCase;
private CheckBox mChkRegexp;
public Search(Activity cntx, AdvancedEditText editText) {
mCntx = cntx;
mEditText = editText;
// The dialog is saved and created on first use
mDialog = null;
}
/**
* Shows the dialog to search.
*/
public void showDialog(){
if(mDialog == null)
public void showDialog() {
if (mDialog == null)
createDialog();
mDialog.show();
}
/**
* Performs a search as defined in the dialog.
* If the search fails the dialog is shown.
*/
public void searchNext() {
if(mDialog == null)
if (mDialog == null)
createDialog();
String searchText = mEdTxt.getText().toString();
if(searchText.isEmpty()) {
if (searchText.isEmpty()) {
// no text to search
showDialog();
return;
}
String text = mEditText.getText().toString();
int flags = 0;
if(!mChkCase.isChecked()) flags |= Pattern.CASE_INSENSITIVE;
if(!mChkRegexp.isChecked()) flags |= Pattern.LITERAL;
if (!mChkCase.isChecked()) flags |= Pattern.CASE_INSENSITIVE;
if (!mChkRegexp.isChecked()) flags |= Pattern.LITERAL;
Pattern pattern = Pattern.compile(searchText, flags);
int start = -1;
int end = -1;
Matcher matcher = pattern.matcher(text);
if(!mChkBackwards.isChecked()) {
if (!mChkBackwards.isChecked()) {
// search fordwards
int from = mEditText.getTrueSelectionStart();
if (from != mEditText.getTrueSelectionEnd()) from++; // avoids returning the current selection
if( matcher.find(from) || matcher.find(0)){
if (from != mEditText.getTrueSelectionEnd())
from++; // avoids returning the current selection
if (matcher.find(from) || matcher.find(0)) {
// found one just after the selection or from the beginning
start = matcher.start();
end = matcher.end();
}
}else{
} else {
// search backwards
int until = mEditText.getTrueSelectionEnd();
while( matcher.find() && matcher.end() < until){
while (matcher.find() && matcher.end() < until) {
// found match before cursor, save
start = matcher.start();
end = matcher.end();
}
if(start == -1){
if (start == -1) {
// not found, continue to find last one
while( matcher.find() ){
while (matcher.find()) {
// found match, save
start = matcher.start();
end = matcher.end();
}
}
}
if( start != -1) {
if (start != -1) {
// found, set selection
mEditText.setSelection(start, end);
}else{
} else {
// nothing found
showDialog();
}
}
/**
* Private: creates the dialog
*/
private void createDialog(){
private void createDialog() {
View views = mCntx.getLayoutInflater().inflate(R.layout.dialog_search, null);
mEdTxt = views.findViewById(R.id.srch_text);
mChkBackwards = views.findViewById(R.id.srch_back);
mChkCase = views.findViewById(R.id.srch_case);
mChkRegexp = views.findViewById(R.id.srch_regexp);
mDialog = new AlertDialog.Builder(mCntx)
.setTitle(R.string.srch_ttl)
.setView(views)

View file

@ -25,7 +25,6 @@ SOFTWARE.
package net.pierrox.lightning_launcher.util;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
@ -46,17 +45,10 @@ import net.pierrox.lightning_launcher_extreme.R;
import java.util.ArrayList;
public class SetVariableDialog extends AlertDialog implements DialogInterface.OnClickListener, View.OnClickListener {
public interface OnSetVariableDialogListener {
public void onSetVariableEdited(Variable variable);
public void onSetVariableCancel();
}
private Variable mInitValue;
private OnSetVariableDialogListener mListener;
private final Variable mInitValue;
private final OnSetVariableDialogListener mListener;
private EditText mNameEditText;
private EditText mValueEditText;
public SetVariableDialog(Context context, Variable init_value, OnSetVariableDialogListener listener) {
super(context);
@ -68,17 +60,17 @@ public class SetVariableDialog extends AlertDialog implements DialogInterface.On
protected void onCreate(Bundle savedInstanceState) {
View view = getLayoutInflater().inflate(R.layout.set_var_dialog, null);
((TextView)view.findViewById(R.id.sv_nt)).setText(R.string.sv_n);
((TextView)view.findViewById(R.id.sv_vt)).setText(R.string.bd_v);
((TextView) view.findViewById(R.id.sv_nt)).setText(R.string.sv_n);
((TextView) view.findViewById(R.id.sv_vt)).setText(R.string.bd_v);
mNameEditText = (EditText) view.findViewById(R.id.sv_n);
mValueEditText = (EditText) view.findViewById(R.id.sv_v);
mNameEditText = view.findViewById(R.id.sv_n);
mValueEditText = view.findViewById(R.id.sv_v);
Button select_var = (Button) view.findViewById(R.id.sv_ns);
Button select_var = view.findViewById(R.id.sv_ns);
select_var.setTypeface(LLApp.get().getIconsTypeface());
select_var.setOnClickListener(this);
if(mInitValue != null) {
if (mInitValue != null) {
mNameEditText.setText(mInitValue.name);
mValueEditText.setText(mInitValue.value.toString());
}
@ -104,7 +96,7 @@ public class SetVariableDialog extends AlertDialog implements DialogInterface.On
@Override
public void afterTextChanged(Editable s) {
ok_button.setEnabled(s.length()>0);
ok_button.setEnabled(s.length() > 0);
}
});
}
@ -133,8 +125,14 @@ public class SetVariableDialog extends AlertDialog implements DialogInterface.On
}
}
public interface OnSetVariableDialogListener {
void onSetVariableEdited(Variable variable);
void onSetVariableCancel();
}
private class VariableSelectionDialog extends AlertDialog implements AdapterView.OnItemClickListener {
private ArrayList<Variable> mUserVariables;
private final ArrayList<Variable> mUserVariables;
public VariableSelectionDialog(Context context) {
super(context);
@ -144,9 +142,9 @@ public class SetVariableDialog extends AlertDialog implements DialogInterface.On
@Override
protected void onCreate(Bundle savedInstanceState) {
if(mUserVariables.size() == 0) {
if (mUserVariables.size() == 0) {
setMessage(getContext().getString(R.string.uv_e));
setButton(BUTTON_POSITIVE, getContext().getString(android.R.string.ok), (OnClickListener)null);
setButton(BUTTON_POSITIVE, getContext().getString(android.R.string.ok), (OnClickListener) null);
} else {
setTitle(R.string.bv_pick);

View file

@ -34,7 +34,6 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.util.DisplayMetrics;
@ -60,10 +59,10 @@ import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.data.LightningIntent;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.PageIndicator;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.data.PageProcessor;
import net.pierrox.lightning_launcher.data.Shortcut;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher_extreme.BuildConfig;
import net.pierrox.lightning_launcher_extreme.R;
@ -73,17 +72,53 @@ import java.io.IOException;
import java.util.ArrayList;
public class Setup {
public interface OnFirstTimeInitEvent {
public void onFirstTimeInitStart(boolean is_import);
public void onFirstTimeInitEnd(boolean success, boolean was_import, Item all_apps_item);
}
private static final String[] CN_DOCK_0 = new String[]{
// phone
"com.android.contacts/.activities.DialtactsActivity",
"com.android.contacts/.DialtactsActivity",
"com.android.contacts/com.android.dialer.DialtactsActivity",
"com.android.dialer/.DialtactsActivity",
"com.android.htccontacts/.DialerTabActivity",
"com.google.android.dialer/.extensions.GoogleDialtactsActivity",
"com.sec.android.app.dialertab/.DialerTabActivity",
"com.sonyericsson.android.socialphonebook/.DialerEntryActivity",
// camera
"com.android.camera/.Camera",
"com.android.camera/.CameraEntry",
"com.asus.camera/.CameraApp",
"com.cyngn.cameranext/com.android.camera.CameraLauncher",
"com.google.android.GoogleCamera/com.android.camera.CameraLauncher",
"com.motorola.camera/.Camera",
"com.sec.android.app.camera/.Camera",
"com.sonyericsson.android.camera/.CameraActivity",
};
private static final String[] CN_DOCK_1 = new String[]{
"com.android.settings/.Settings",
"com.android.settings/.GridSettings",
};
// private static final String[] CN_DOCK_2 = new String[] {
// "net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.AppDrawerX"
// };
private static final String[] CN_DOCK_3 = new String[]{
"com.android.chrome/com.google.android.apps.chrome.Main",
"com.android.browser/.BrowserActivity",
"com.asus.browser/com.android.browser.BrowserActivity",
"com.opera.mini.android/.Browser",
"com.sec.android.app.sbrowser/.SBrowserMainActivity",
};
private static final String[] CN_DOCK_4 = new String[]{
"com.android.vending/.AssetBrowserActivity"
};
@SuppressWarnings("deprecation")
public static void firstTimeInit(final OnFirstTimeInitEvent listener) {
final LightningEngine engine = LLApp.get().getAppEngine();
Context tmp = null;
if(!BuildConfig.IS_TRIAL) {
if (!BuildConfig.IS_TRIAL) {
try {
tmp = LLApp.get().createPackageContext(LLApp.LL_PKG_NAME, 0);
} catch (PackageManager.NameNotFoundException e) {
@ -104,7 +139,7 @@ public class Setup {
protected Boolean doInBackground(Void... params) {
was_import = import_data;
if(!import_data) {
if (!import_data) {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
@ -122,7 +157,7 @@ public class Setup {
// ll is here but no valid data
engine.reloadGlobalConfig();
if(engine.shouldDoFirstTimeInit()) {
if (engine.shouldDoFirstTimeInit()) {
was_import = false;
mAllAppsItem = defaultSetup(engine);
return true;
@ -131,7 +166,7 @@ public class Setup {
LightningEngine.PageManager pageManager = engine.getPageManager();
pageManager.clear();
ArrayList<Page> mImportedPages = new ArrayList<>();
for(int p : pageManager.getAllPagesIds()) {
for (int p : pageManager.getAllPagesIds()) {
mImportedPages.add(pageManager.getOrLoadPage(p));
}
@ -156,55 +191,13 @@ public class Setup {
}
}.execute((Void)null);
}.execute((Void) null);
}
private static final String[] CN_DOCK_0 = new String[] {
// phone
"com.android.contacts/.activities.DialtactsActivity",
"com.android.contacts/.DialtactsActivity",
"com.android.contacts/com.android.dialer.DialtactsActivity",
"com.android.dialer/.DialtactsActivity",
"com.android.htccontacts/.DialerTabActivity",
"com.google.android.dialer/.extensions.GoogleDialtactsActivity",
"com.sec.android.app.dialertab/.DialerTabActivity",
"com.sonyericsson.android.socialphonebook/.DialerEntryActivity",
// camera
"com.android.camera/.Camera",
"com.android.camera/.CameraEntry",
"com.asus.camera/.CameraApp",
"com.cyngn.cameranext/com.android.camera.CameraLauncher",
"com.google.android.GoogleCamera/com.android.camera.CameraLauncher",
"com.motorola.camera/.Camera",
"com.sec.android.app.camera/.Camera",
"com.sonyericsson.android.camera/.CameraActivity",
};
private static final String[] CN_DOCK_1 = new String[] {
"com.android.settings/.Settings",
"com.android.settings/.GridSettings",
};
// private static final String[] CN_DOCK_2 = new String[] {
// "net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.AppDrawerX"
// };
private static final String[] CN_DOCK_3 = new String[] {
"com.android.chrome/com.google.android.apps.chrome.Main",
"com.android.browser/.BrowserActivity",
"com.asus.browser/com.android.browser.BrowserActivity",
"com.opera.mini.android/.Browser",
"com.sec.android.app.sbrowser/.SBrowserMainActivity",
};
private static final String[] CN_DOCK_4 = new String[] {
"com.android.vending/.AssetBrowserActivity"
};
private static Item defaultSetup(LightningEngine engine) {
File dir = engine.getBaseDir();
if(!dir.exists()) {
if (!dir.exists()) {
dir.mkdirs();
}
Utils.deleteDirectory(dir, false);
@ -219,8 +212,8 @@ public class Setup {
GlobalConfig globalConfig = engine.getGlobalConfig();
if(!BuildConfig.IS_TRIAL || LLApp.get().isTrialVersion()) {
Page lockscreen = engine.getOrLoadPage(Page.FIRST_DASHBOARD_PAGE+1);
if (!BuildConfig.IS_TRIAL || LLApp.get().isTrialVersion()) {
Page lockscreen = engine.getOrLoadPage(Page.FIRST_DASHBOARD_PAGE + 1);
setupLockScreen(lockscreen);
globalConfig.screensOrder = new int[2];
@ -234,7 +227,7 @@ public class Setup {
}
// create dashboard default config
int page= Page.FIRST_DASHBOARD_PAGE;
int page = Page.FIRST_DASHBOARD_PAGE;
Page dashboard = pm.getOrLoadPage(page);
Item all_apps_item = setupDashboard(dashboard, drawer);
@ -258,7 +251,6 @@ public class Setup {
int color_primary_dark = resources.getColor(R.color.color_primary_dark);
final PageConfig dashboard_config = dashboard.config;
dashboard_config.applyDefaultFolderConfig();
dashboard_config.defaultFolderConfig.outsideTapClose = true;
@ -302,7 +294,7 @@ public class Setup {
ic.box_s = ic.box.toString(dashboard_config.defaultItemConfig.box);
pi.notifyChanged();
if(!LLApp.get().isFreeVersion()) {
if (!LLApp.get().isFreeVersion()) {
// install date and time dynamic texts
DynamicText dt = Utils.addDynamicText(dashboard, DynamicTextConfig.Source.DATE, true);
dt.getCell().set(3, 4, 5, 5);
@ -348,7 +340,7 @@ public class Setup {
// hints
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.WIKI_PREFIX+"desktops"));
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.WIKI_PREFIX + "desktops"));
s = Utils.addShortcut(resources.getString(R.string.ds_hn), null, intent, dashboard, 6, 2, 1, true);
s.getCell().set(6, 2, 9, 3);
sc = s.modifyShortcutConfig();
@ -356,7 +348,7 @@ public class Setup {
sc.labelMaxLines = 7;
s.notifyChanged();
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.WIKI_PREFIX+"concepts"));
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.WIKI_PREFIX + "concepts"));
s = Utils.addShortcut(resources.getString(R.string.ds_um), null, intent, dashboard, 6, 2, 1, true);
s.getCell().set(-4, 2, -1, 3);
sc = s.modifyShortcutConfig();
@ -365,54 +357,53 @@ public class Setup {
s.notifyChanged();
// start here folder
Folder start_here;
Page start_here_page;
start_here=Utils.addFolder(dashboard, 2, 1, 1, true, resources.getString(R.string.ds_sh));
start_here = Utils.addFolder(dashboard, 2, 1, 1, true, resources.getString(R.string.ds_sh));
start_here.getCell().set(0, 0, 1, 1);
FolderConfig fc = start_here.modifyFolderConfig();
fc.iconStyle= FolderConfig.FolderIconStyle.NORMAL;
fc.iconStyle = FolderConfig.FolderIconStyle.NORMAL;
fc.titleVisibility = false;
fc.wAH = Box.AlignH.LEFT;
// fc.wAV = Box.AlignV.TOP;
fc.animationIn = FolderConfig.FolderAnimation.SLIDE_FROM_LEFT;
fc.animationOut = FolderConfig.FolderAnimation.SLIDE_FROM_RIGHT;
fc.autoClose = true;
Bitmap icon= Utils.createIconFromText(start_here.getStdIconSize(), "q");
Bitmap icon = Utils.createIconFromText(start_here.getStdIconSize(), "q");
Utils.saveIconToFile(start_here.getDefaultIconFile(), icon);
start_here_page = start_here.getOrLoadFolderPage();
PageConfig folder_config=start_here_page.config;
folder_config.defaultShortcutConfig.labelMaxLines=2;
PageConfig folder_config = start_here_page.config;
folder_config.defaultShortcutConfig.labelMaxLines = 2;
folder_config.useDesktopSize = false;
// folder_config.gridPRowMode = PageConfig.SizeMode.AUTO;
folder_config.gridPRowNum = 6;
folder_config.gridPColumnMode= PageConfig.SizeMode.AUTO;
folder_config.gridPColumnMode = PageConfig.SizeMode.AUTO;
start_here.notifyChanged();
start_here_page.saveConfig();
final String youtube="http://www.youtube.com/watch?v=";
installShortcut(start_here_page, 0, 0, "u", resources.getString(R.string.tut_concepts), Version.WIKI_PREFIX+"concepts", null);
installShortcut(start_here_page, 0, 1, "a", resources.getString(R.string.tut_wiki), Version.WIKI_PREFIX+"start", null);
final String youtube = "http://www.youtube.com/watch?v=";
installShortcut(start_here_page, 0, 0, "u", resources.getString(R.string.tut_concepts), Version.WIKI_PREFIX + "concepts", null);
installShortcut(start_here_page, 0, 1, "a", resources.getString(R.string.tut_wiki), Version.WIKI_PREFIX + "start", null);
installShortcut(start_here_page, 0, 2, "y", resources.getString(R.string.language_t), Version.LANGUAGE_PACK_INSTALL_URI.toString(), null);
installShortcut(start_here_page, 0, 3, "r", resources.getString(R.string.ds_uc), Version.USER_COMMUNITY, null);
installShortcut(start_here_page, 0, 4, "t", resources.getString(R.string.tut_intro), youtube+"muY61GMH3mQ", null);
installShortcut(start_here_page, 0, 4, "t", resources.getString(R.string.tut_intro), youtube + "muY61GMH3mQ", null);
// start here tutorials folder
Folder tutorials;
Page tutorials_page;
tutorials=Utils.addFolder(start_here_page, 0, 5, 1, true, resources.getString(R.string.tutorials));
tutorials = Utils.addFolder(start_here_page, 0, 5, 1, true, resources.getString(R.string.tutorials));
tutorials.getCell().set(0, 5, 1, 6);
start_here_page.getAndCreateIconDir();
icon = Utils.createIconFromText(Utils.getStandardIconSize(), "v");
Utils.saveIconToFile(tutorials.getDefaultIconFile(), icon);
fc = tutorials.modifyFolderConfig();
fc.iconStyle= FolderConfig.FolderIconStyle.NORMAL;
fc.iconStyle = FolderConfig.FolderIconStyle.NORMAL;
fc.titleVisibility = false;
fc.wAH = Box.AlignH.LEFT;
// fc.wAV = Box.AlignV.TOP;
@ -422,14 +413,14 @@ public class Setup {
tutorials_page = tutorials.getOrLoadFolderPage();
tutorials_page.config.useDesktopSize = false;
tutorials_page.config.gridPColumnMode= PageConfig.SizeMode.AUTO;
tutorials_page.config.gridPColumnMode = PageConfig.SizeMode.AUTO;
tutorials.notifyChanged();
installShortcut(tutorials_page, 0, 0, "s", resources.getString(R.string.ds_tt), Version.WIKI_PREFIX + "tips_tricks", null);
installShortcut(tutorials_page, 0, 1, "v", resources.getString(R.string.tut_custo), youtube+"Gkh_RdH8FTk", null);
installShortcut(tutorials_page, 0, 2, "v", resources.getString(R.string.tut_pin), youtube+"eUFgtyea5Ak", null);
installShortcut(tutorials_page, 0, 3, "v", resources.getString(R.string.tut_scroll), youtube+"4Kic7av9eac", null);
installShortcut(tutorials_page, 0, 1, "v", resources.getString(R.string.tut_custo), youtube + "Gkh_RdH8FTk", null);
installShortcut(tutorials_page, 0, 2, "v", resources.getString(R.string.tut_pin), youtube + "eUFgtyea5Ak", null);
installShortcut(tutorials_page, 0, 3, "v", resources.getString(R.string.tut_scroll), youtube + "4Kic7av9eac", null);
return all_apps_item;
}
@ -484,7 +475,7 @@ public class Setup {
private static Item findItem(ArrayList<Item> items, String[] component_names) {
// try to match package and class first, otherwise try to match the package only
Item item = findItemByPackageName(items, component_names, false);
if(item == null) {
if (item == null) {
item = findItemByPackageName(items, component_names, true);
}
@ -492,13 +483,13 @@ public class Setup {
}
private static Item findItemByPackageName(ArrayList<Item> items, String[] component_names, boolean package_only) {
for(Item i : items) {
if(!(i instanceof Shortcut)) continue;
for (Item i : items) {
if (!(i instanceof Shortcut)) continue;
Shortcut s=(Shortcut)i;
Intent intent=s.getIntent();
Shortcut s = (Shortcut) i;
Intent intent = s.getIntent();
final ComponentName item_cn = intent.getComponent();
if(item_cn != null) {
if (item_cn != null) {
final String item_pkg = item_cn.getPackageName();
for (String cn_s : component_names) {
ComponentName cn = ComponentName.unflattenFromString(cn_s);
@ -514,11 +505,11 @@ public class Setup {
private static Item installDockShortcut(Page dashboard, Page app_drawer, int x, int y, String[] component_names) {
Item item = findItem(app_drawer.items, component_names);
if(item != null) {
if (item != null) {
Shortcut shortcut = Utils.copyShortcut(item, dashboard, x, y, 1);
ItemConfig ic_dock=shortcut.modifyItemConfig();
ic_dock.pinMode=ItemConfig.PinMode.XY;
ItemConfig ic_dock = shortcut.modifyItemConfig();
ic_dock.pinMode = ItemConfig.PinMode.XY;
// ic_dock.rotate=true;
ic_dock.box.av = Box.AlignV.BOTTOM;
ic_dock.box_s = ic_dock.box.toString(null);
@ -528,7 +519,7 @@ public class Setup {
sc_dock.iconReflectionOverlap = 0;
sc_dock.iconReflectionSize = 0.7f;
sc_dock.labelVisibility = false;
shortcut.getCell().set(x, y, x+1, y+1);
shortcut.getCell().set(x, y, x + 1, y + 1);
shortcut.notifyChanged();
@ -539,14 +530,14 @@ public class Setup {
}
private static void installShortcut(Page page, int x, int y, String icon_code, String label, String uri, Intent intent) {
if(intent==null) {
intent=new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
if (intent == null) {
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
}
Shortcut new_item=new Shortcut(page);
int new_id=page.findFreeItemId();
File icon_dir=page.getAndCreateIconDir();
Shortcut new_item = new Shortcut(page);
int new_id = page.findFreeItemId();
File icon_dir = page.getAndCreateIconDir();
icon_dir.mkdirs();
new_item.init(new_id, new Rect(x, y, x+1, y+1), null, label, intent);
new_item.init(new_id, new Rect(x, y, x + 1, y + 1), null, label, intent);
int size = Utils.getStandardIconSize();
Bitmap icon = Utils.createIconFromText(size, icon_code);
Utils.saveIconToFile(new_item.getCustomIconFile(), icon);
@ -562,13 +553,13 @@ public class Setup {
int color_primary_dark = resources.getColor(R.color.color_primary_dark);
Page page = engine.getOrLoadPage(Page.USER_MENU_PAGE);
PageConfig page_config=page.config;
PageConfig page_config = page.config;
page_config.gridPColumnNum = 5;
// page_config.gridPRowNum = 7;
page_config.gridPRowMode = PageConfig.SizeMode.AUTO;
// page_config.gridPRowSize = (int)(large_icon_size * resources.getDisplayMetrics().scaledDensity * 1.5f);
File icon_dir=page.getAndCreateIconDir();
File icon_dir = page.getAndCreateIconDir();
icon_dir.mkdirs();
Folder folder = new Folder(page);
@ -616,17 +607,23 @@ public class Setup {
Shortcut shortcut;
Intent intent;
File icon_dir=page.getAndCreateIconDir();
File icon_dir = page.getAndCreateIconDir();
id = page.findFreeItemId();
shortcut = new Shortcut(page);
intent = new Intent(context, Dashboard.class);
intent.putExtra(LightningIntent.INTENT_EXTRA_ACTION, GlobalConfig.RUN_SCRIPT);
intent.putExtra(LightningIntent.INTENT_EXTRA_DATA, String.valueOf(ScriptManager.BUILTIN_USER_MENU));
shortcut.init(id, new Rect(x, 0, x+1, 1), null, label, intent);
shortcut.init(id, new Rect(x, 0, x + 1, 1), null, label, intent);
shortcut.setName(name);
Bitmap icon = Utils.createIconFromText(shortcut.getStdIconSize(), icon_code);
Utils.saveIconToFile(shortcut.getDefaultIconFile(), icon);
page.addItem(shortcut);
}
public interface OnFirstTimeInitEvent {
void onFirstTimeInitStart(boolean is_import);
void onFirstTimeInitEnd(boolean success, boolean was_import, Item all_apps_item);
}
}

View file

@ -24,7 +24,6 @@ SOFTWARE.
package net.pierrox.lightning_launcher.views;
import net.pierrox.lightning_launcher_extreme.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@ -34,298 +33,373 @@ import android.graphics.Paint.FontMetrics;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import net.pierrox.lightning_launcher_extreme.R;
public class BoxEditorView extends View implements Runnable {
public interface OnBoxEditorEventListener {
public void onBoxSelectionChanged(Object token, int selection);
}
public static final int SEG_ML = 0;
public static final int SEG_MT = 1;
public static final int SEG_MR = 2;
public static final int SEG_MB = 3;
public static final int SEG_BL = 4;
public static final int SEG_BT = 5;
public static final int SEG_BR = 6;
public static final int SEG_BB = 7;
public static final int SEG_PL = 8;
public static final int SEG_PT = 9;
public static final int SEG_PR = 10;
public static final int SEG_PB = 11;
public static final int SEG_CONTENT = 12;
private static final int ALL_MARGINGS = 1<<SEG_ML | 1<<SEG_MT | 1<<SEG_MR | 1<<SEG_MB;
private static final int ALL_BORDERS = 1<<SEG_BL | 1<<SEG_BT | 1<<SEG_BR | 1<<SEG_BB;
private static final int ALL_PADDINGS = 1<<SEG_PL | 1<<SEG_PT | 1<<SEG_PR | 1<<SEG_PB;
public static final int SEG_SELECTION_COLOR_MASK = 1<<SEG_BL | 1<<SEG_BT | 1<<SEG_BR | 1<<SEG_BB | 1<<SEG_CONTENT;
private static final int DIVIDER=8;
private String mMargin, mBorder, mPadding, mContent, mLeft, mTop, mRight, mBottom;
private Paint mCountourPlainPaint;
private Paint mCountourDashPaint;
private Paint mBorderAreaPaint;
private Paint mSelectedAreaPaint;
private Paint mTextPaint;
private FontMetrics mTextMetrics;
private RectF mOuterRect = new RectF();
private RectF mMarginRect = new RectF();
private RectF mBorderRect = new RectF();
private RectF mPaddingRect = new RectF();
private Path[] mAreas = new Path[13];
private int mSelectedSegments;
public static final int SEG_ML = 0;
public static final int SEG_MT = 1;
public static final int SEG_MR = 2;
public static final int SEG_MB = 3;
public static final int SEG_BL = 4;
public static final int SEG_BT = 5;
public static final int SEG_BR = 6;
public static final int SEG_BB = 7;
public static final int SEG_PL = 8;
public static final int SEG_PT = 9;
public static final int SEG_PR = 10;
public static final int SEG_PB = 11;
public static final int SEG_CONTENT = 12;
public static final int SEG_SELECTION_COLOR_MASK = 1 << SEG_BL | 1 << SEG_BT | 1 << SEG_BR | 1 << SEG_BB | 1 << SEG_CONTENT;
private static final int ALL_MARGINGS = 1 << SEG_ML | 1 << SEG_MT | 1 << SEG_MR | 1 << SEG_MB;
private static final int ALL_BORDERS = 1 << SEG_BL | 1 << SEG_BT | 1 << SEG_BR | 1 << SEG_BB;
private static final int ALL_PADDINGS = 1 << SEG_PL | 1 << SEG_PT | 1 << SEG_PR | 1 << SEG_PB;
private static final int DIVIDER = 8;
private final String mMargin;
private final String mBorder;
private final String mPadding;
private final String mContent;
private final String mLeft;
private final String mTop;
private final String mRight;
private final String mBottom;
private final Paint mCountourPlainPaint;
private final Paint mCountourDashPaint;
private final Paint mBorderAreaPaint;
private final Paint mSelectedAreaPaint;
private final Paint mTextPaint;
private final RectF mOuterRect = new RectF();
private final RectF mMarginRect = new RectF();
private final RectF mBorderRect = new RectF();
private final RectF mPaddingRect = new RectF();
private final Path[] mAreas = new Path[13];
private FontMetrics mTextMetrics;
private int mSelectedSegments;
private int mTouchedSegment;
private Object mOnBoxEditorEventToken;
private OnBoxEditorEventListener mOnBoxEditorEventListener;
private boolean mHasLongClicked;
public BoxEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
mMargin=context.getString(R.string.margin);
mBorder=context.getString(R.string.border);
mPadding=context.getString(R.string.padding);
mContent=context.getString(R.string.content);
mLeft=context.getString(R.string.left);
mTop=context.getString(R.string.top);
mRight=context.getString(R.string.right);
mBottom=context.getString(R.string.bottom);
mCountourPlainPaint = new Paint();
mCountourPlainPaint.setStyle(Paint.Style.STROKE);
mCountourPlainPaint.setColor(Color.BLACK);
mCountourDashPaint = new Paint();
mCountourDashPaint.setStyle(Paint.Style.STROKE);
mCountourDashPaint.setColor(Color.BLACK);
mCountourDashPaint.setPathEffect(new DashPathEffect(new float[] { 5, 5 }, 0));
mBorderAreaPaint = new Paint();
mBorderAreaPaint.setStyle(Paint.Style.FILL);
mBorderAreaPaint.setColor(0xffb0b0b0);
mSelectedAreaPaint = new Paint();
mSelectedAreaPaint.setStyle(Paint.Style.FILL);
private Object mOnBoxEditorEventToken;
private OnBoxEditorEventListener mOnBoxEditorEventListener;
private boolean mHasLongClicked;
public BoxEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
mMargin = context.getString(R.string.margin);
mBorder = context.getString(R.string.border);
mPadding = context.getString(R.string.padding);
mContent = context.getString(R.string.content);
mLeft = context.getString(R.string.left);
mTop = context.getString(R.string.top);
mRight = context.getString(R.string.right);
mBottom = context.getString(R.string.bottom);
mCountourPlainPaint = new Paint();
mCountourPlainPaint.setStyle(Paint.Style.STROKE);
mCountourPlainPaint.setColor(Color.BLACK);
mCountourDashPaint = new Paint();
mCountourDashPaint.setStyle(Paint.Style.STROKE);
mCountourDashPaint.setColor(Color.BLACK);
mCountourDashPaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0));
mBorderAreaPaint = new Paint();
mBorderAreaPaint.setStyle(Paint.Style.FILL);
mBorderAreaPaint.setColor(0xffb0b0b0);
mSelectedAreaPaint = new Paint();
mSelectedAreaPaint.setStyle(Paint.Style.FILL);
mSelectedAreaPaint.setColor(0x808080ff); // workaround for a drawing bug on some devices
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int max = getResources().getDimensionPixelSize(R.dimen.max_box_editor_width);
if(w>max) w=max;
setMeasuredDimension(w, w*2/3);
}
if (w > max) w = max;
setMeasuredDimension(w, w * 2 / 3);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
final int sw = (w < h ? w : h) / DIVIDER;
final int sh = sw;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
final int sw=(w<h ? w : h)/DIVIDER;
final int sh=sw;
int ol=sw/2;
int ot=sh/2;
int or=w-sw/2;
int ob=h-sh/2;
int ml=ol+sw;
int mt=ot+sh;
int mr=or-sw;
int mb=ob-sh;
int bl=ml+sw;
int bt=mt+sh;
int br=mr-sw;
int bb=mb-sh;
int pl=bl+sw;
int pt=bt+sh;
int pr=br-sw;
int pb=bb-sh;
mOuterRect.set(ol, ot, or, ob);
mMarginRect.set(ml, mt, mr, mb);
mBorderRect.set(bl, bt, br, bb);
mPaddingRect.set(pl, pt, pr, pb);
Path p;
p = new Path(); p.moveTo(ol, ot); p.lineTo(ml, mt); p.lineTo(ml, mb); p.lineTo(ol, ob); p.close(); mAreas[SEG_ML] = p;
p = new Path(); p.moveTo(ol, ot); p.lineTo(or, ot); p.lineTo(mr, mt); p.lineTo(ml, mt); p.close(); mAreas[SEG_MT] = p;
p = new Path(); p.moveTo(or, ot); p.lineTo(or, ob); p.lineTo(mr, mb); p.lineTo(mr, mt); p.close(); mAreas[SEG_MR] = p;
p = new Path(); p.moveTo(ol, ob); p.lineTo(ml, mb); p.lineTo(mr, mb); p.lineTo(or, ob); p.close(); mAreas[SEG_MB] = p;
int ol = sw / 2;
int ot = sh / 2;
int or = w - sw / 2;
int ob = h - sh / 2;
p = new Path(); p.moveTo(ml, mt); p.lineTo(bl, bt); p.lineTo(bl, bb); p.lineTo(ml, mb); p.close(); mAreas[SEG_BL] = p;
p = new Path(); p.moveTo(ml, mt); p.lineTo(mr, mt); p.lineTo(br, bt); p.lineTo(bl, bt); p.close(); mAreas[SEG_BT] = p;
p = new Path(); p.moveTo(mr, mt); p.lineTo(mr, mb); p.lineTo(br, bb); p.lineTo(br, bt); p.close(); mAreas[SEG_BR] = p;
p = new Path(); p.moveTo(ml, mb); p.lineTo(bl, bb); p.lineTo(br, bb); p.lineTo(mr, mb); p.close(); mAreas[SEG_BB] = p;
p = new Path(); p.moveTo(bl, bt); p.lineTo(pl, pt); p.lineTo(pl, pb); p.lineTo(bl, bb); p.close(); mAreas[SEG_PL] = p;
p = new Path(); p.moveTo(bl, bt); p.lineTo(br, bt); p.lineTo(pr, pt); p.lineTo(pl, pt); p.close(); mAreas[SEG_PT] = p;
p = new Path(); p.moveTo(br, bt); p.lineTo(br, bb); p.lineTo(pr, pb); p.lineTo(pr, pt); p.close(); mAreas[SEG_PR] = p;
p = new Path(); p.moveTo(bl, bb); p.lineTo(pl, pb); p.lineTo(pr, pb); p.lineTo(br, bb); p.close(); mAreas[SEG_PB] = p;
p = new Path(); p.moveTo(bl, bt); p.lineTo(br, bt); p.lineTo(br, bb); p.lineTo(bl, bb); p.close(); mAreas[SEG_CONTENT] = p;
mTextPaint.setTextSize(sh/2);
mTextMetrics = mTextPaint.getFontMetrics();
}
int ml = ol + sw;
int mt = ot + sh;
int mr = or - sw;
int mb = ob - sh;
@Override
protected void onDraw(Canvas canvas) {
final int w = getWidth();
final int h = getHeight();
final int sw=(w<h ? w : h)/DIVIDER;
final int sh=sw;
canvas.drawARGB(255, 255, 255, 255);
canvas.drawPath(mAreas[SEG_BL], mBorderAreaPaint);
canvas.drawPath(mAreas[SEG_BT], mBorderAreaPaint);
canvas.drawPath(mAreas[SEG_BR], mBorderAreaPaint);
canvas.drawPath(mAreas[SEG_BB], mBorderAreaPaint);
for(int i=0; i<mAreas.length; i++) {
drawArea(canvas, i);
}
canvas.drawRect(mOuterRect, mCountourDashPaint);
canvas.drawRect(mMarginRect, mCountourPlainPaint);
canvas.drawRect(mBorderRect, mCountourPlainPaint);
canvas.drawRect(mPaddingRect, mCountourDashPaint);
final float w2=w/2;
final float h2=h/2;
final float dh = (sh-mTextMetrics.ascent-mTextMetrics.descent)/2;
canvas.drawText(mContent, w2, mPaddingRect.top+(mPaddingRect.height()-mTextMetrics.ascent-mTextMetrics.descent)/2, mTextPaint);
canvas.drawText(mMargin+" "+mTop, w2, mOuterRect.top+dh, mTextPaint);
canvas.drawText(mBorder+" "+mTop, w2, mMarginRect.top+dh, mTextPaint);
canvas.drawText(mPadding+" "+mTop, w2, mBorderRect.top+dh, mTextPaint);
canvas.drawText(mMargin+" "+mBottom, w2, mMarginRect.bottom+dh, mTextPaint);
canvas.drawText(mBorder+" "+mBottom, w2, mBorderRect.bottom+dh, mTextPaint);
canvas.drawText(mPadding+" "+mBottom, w2, mPaddingRect.bottom+dh, mTextPaint);
canvas.save();
final float rx_r=mOuterRect.right-dh;
canvas.rotate(90, rx_r, h2);
canvas.drawText(mMargin+" "+mRight, rx_r, h2, mTextPaint);
canvas.drawText(mBorder+" "+mRight, rx_r, h2+sh, mTextPaint);
canvas.drawText(/*mPadding+" "+*/mRight, rx_r, h2+sh*2, mTextPaint);
canvas.restore();
canvas.save();
final float rx_l=mOuterRect.left+dh;
canvas.rotate(-90, rx_l, h2);
canvas.drawText(mMargin+" "+mLeft, rx_l, h2, mTextPaint);
canvas.drawText(mBorder+" "+mLeft, rx_l, h2+sh, mTextPaint);
canvas.drawText(/*mPadding+" "+*/mLeft, rx_l, h2+sh*2, mTextPaint);
canvas.restore();
}
int bl = ml + sw;
int bt = mt + sh;
int br = mr - sw;
int bb = mb - sh;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
mHasLongClicked = false;
postDelayed(this, ViewConfiguration.getLongPressTimeout());
int pl = bl + sw;
int pt = bt + sh;
int pr = br - sw;
int pb = bb - sh;
mTouchedSegment = -1;
Region r = new Region();
Region clip = new Region(0, 0, getWidth(), getHeight());
for(int i=0; i<mAreas.length; i++) {
Path p = mAreas[i];
r.setPath(p, clip);
if(r.contains((int)event.getX(), (int)event.getY())) {
mTouchedSegment = i;
break;
mOuterRect.set(ol, ot, or, ob);
mMarginRect.set(ml, mt, mr, mb);
mBorderRect.set(bl, bt, br, bb);
mPaddingRect.set(pl, pt, pr, pb);
Path p;
p = new Path();
p.moveTo(ol, ot);
p.lineTo(ml, mt);
p.lineTo(ml, mb);
p.lineTo(ol, ob);
p.close();
mAreas[SEG_ML] = p;
p = new Path();
p.moveTo(ol, ot);
p.lineTo(or, ot);
p.lineTo(mr, mt);
p.lineTo(ml, mt);
p.close();
mAreas[SEG_MT] = p;
p = new Path();
p.moveTo(or, ot);
p.lineTo(or, ob);
p.lineTo(mr, mb);
p.lineTo(mr, mt);
p.close();
mAreas[SEG_MR] = p;
p = new Path();
p.moveTo(ol, ob);
p.lineTo(ml, mb);
p.lineTo(mr, mb);
p.lineTo(or, ob);
p.close();
mAreas[SEG_MB] = p;
p = new Path();
p.moveTo(ml, mt);
p.lineTo(bl, bt);
p.lineTo(bl, bb);
p.lineTo(ml, mb);
p.close();
mAreas[SEG_BL] = p;
p = new Path();
p.moveTo(ml, mt);
p.lineTo(mr, mt);
p.lineTo(br, bt);
p.lineTo(bl, bt);
p.close();
mAreas[SEG_BT] = p;
p = new Path();
p.moveTo(mr, mt);
p.lineTo(mr, mb);
p.lineTo(br, bb);
p.lineTo(br, bt);
p.close();
mAreas[SEG_BR] = p;
p = new Path();
p.moveTo(ml, mb);
p.lineTo(bl, bb);
p.lineTo(br, bb);
p.lineTo(mr, mb);
p.close();
mAreas[SEG_BB] = p;
p = new Path();
p.moveTo(bl, bt);
p.lineTo(pl, pt);
p.lineTo(pl, pb);
p.lineTo(bl, bb);
p.close();
mAreas[SEG_PL] = p;
p = new Path();
p.moveTo(bl, bt);
p.lineTo(br, bt);
p.lineTo(pr, pt);
p.lineTo(pl, pt);
p.close();
mAreas[SEG_PT] = p;
p = new Path();
p.moveTo(br, bt);
p.lineTo(br, bb);
p.lineTo(pr, pb);
p.lineTo(pr, pt);
p.close();
mAreas[SEG_PR] = p;
p = new Path();
p.moveTo(bl, bb);
p.lineTo(pl, pb);
p.lineTo(pr, pb);
p.lineTo(br, bb);
p.close();
mAreas[SEG_PB] = p;
p = new Path();
p.moveTo(bl, bt);
p.lineTo(br, bt);
p.lineTo(br, bb);
p.lineTo(bl, bb);
p.close();
mAreas[SEG_CONTENT] = p;
mTextPaint.setTextSize(sh / 2);
mTextMetrics = mTextPaint.getFontMetrics();
}
@Override
protected void onDraw(Canvas canvas) {
final int w = getWidth();
final int h = getHeight();
final int sw = (w < h ? w : h) / DIVIDER;
final int sh = sw;
canvas.drawARGB(255, 255, 255, 255);
canvas.drawPath(mAreas[SEG_BL], mBorderAreaPaint);
canvas.drawPath(mAreas[SEG_BT], mBorderAreaPaint);
canvas.drawPath(mAreas[SEG_BR], mBorderAreaPaint);
canvas.drawPath(mAreas[SEG_BB], mBorderAreaPaint);
for (int i = 0; i < mAreas.length; i++) {
drawArea(canvas, i);
}
canvas.drawRect(mOuterRect, mCountourDashPaint);
canvas.drawRect(mMarginRect, mCountourPlainPaint);
canvas.drawRect(mBorderRect, mCountourPlainPaint);
canvas.drawRect(mPaddingRect, mCountourDashPaint);
final float w2 = w / 2;
final float h2 = h / 2;
final float dh = (sh - mTextMetrics.ascent - mTextMetrics.descent) / 2;
canvas.drawText(mContent, w2, mPaddingRect.top + (mPaddingRect.height() - mTextMetrics.ascent - mTextMetrics.descent) / 2, mTextPaint);
canvas.drawText(mMargin + " " + mTop, w2, mOuterRect.top + dh, mTextPaint);
canvas.drawText(mBorder + " " + mTop, w2, mMarginRect.top + dh, mTextPaint);
canvas.drawText(mPadding + " " + mTop, w2, mBorderRect.top + dh, mTextPaint);
canvas.drawText(mMargin + " " + mBottom, w2, mMarginRect.bottom + dh, mTextPaint);
canvas.drawText(mBorder + " " + mBottom, w2, mBorderRect.bottom + dh, mTextPaint);
canvas.drawText(mPadding + " " + mBottom, w2, mPaddingRect.bottom + dh, mTextPaint);
canvas.save();
final float rx_r = mOuterRect.right - dh;
canvas.rotate(90, rx_r, h2);
canvas.drawText(mMargin + " " + mRight, rx_r, h2, mTextPaint);
canvas.drawText(mBorder + " " + mRight, rx_r, h2 + sh, mTextPaint);
canvas.drawText(/*mPadding+" "+*/mRight, rx_r, h2 + sh * 2, mTextPaint);
canvas.restore();
canvas.save();
final float rx_l = mOuterRect.left + dh;
canvas.rotate(-90, rx_l, h2);
canvas.drawText(mMargin + " " + mLeft, rx_l, h2, mTextPaint);
canvas.drawText(mBorder + " " + mLeft, rx_l, h2 + sh, mTextPaint);
canvas.drawText(/*mPadding+" "+*/mLeft, rx_l, h2 + sh * 2, mTextPaint);
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mHasLongClicked = false;
postDelayed(this, ViewConfiguration.getLongPressTimeout());
mTouchedSegment = -1;
Region r = new Region();
Region clip = new Region(0, 0, getWidth(), getHeight());
for (int i = 0; i < mAreas.length; i++) {
Path p = mAreas[i];
r.setPath(p, clip);
if (r.contains((int) event.getX(), (int) event.getY())) {
mTouchedSegment = i;
break;
}
}
}
return true;
case MotionEvent.ACTION_UP:
if(!mHasLongClicked) {
removeCallbacks(this);
if(mTouchedSegment != -1) {
mSelectedSegments ^= (1<<mTouchedSegment);
invalidate();
mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments);
}
}
return true;
case MotionEvent.ACTION_CANCEL:
removeCallbacks(this);
return true;
}
return super.onTouchEvent(event);
}
@Override
public void run() {
mHasLongClicked = true;
if(mTouchedSegment >= SEG_ML && mTouchedSegment <= SEG_MB) {
if((mSelectedSegments & ALL_MARGINGS) == ALL_MARGINGS) {
return true;
case MotionEvent.ACTION_UP:
if (!mHasLongClicked) {
removeCallbacks(this);
if (mTouchedSegment != -1) {
mSelectedSegments ^= (1 << mTouchedSegment);
invalidate();
mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments);
}
}
return true;
case MotionEvent.ACTION_CANCEL:
removeCallbacks(this);
return true;
}
return super.onTouchEvent(event);
}
@Override
public void run() {
mHasLongClicked = true;
if (mTouchedSegment >= SEG_ML && mTouchedSegment <= SEG_MB) {
if ((mSelectedSegments & ALL_MARGINGS) == ALL_MARGINGS) {
mSelectedSegments &= ~ALL_MARGINGS;
} else {
mSelectedSegments |= ALL_MARGINGS;
}
} else if(mTouchedSegment >= SEG_BL && mTouchedSegment <= SEG_BB) {
if((mSelectedSegments & ALL_BORDERS) == ALL_BORDERS) {
} else if (mTouchedSegment >= SEG_BL && mTouchedSegment <= SEG_BB) {
if ((mSelectedSegments & ALL_BORDERS) == ALL_BORDERS) {
mSelectedSegments &= ~ALL_BORDERS;
} else {
mSelectedSegments |= ALL_BORDERS;
}
} else if(mTouchedSegment >= SEG_PL && mTouchedSegment <= SEG_PB) {
if((mSelectedSegments & ALL_PADDINGS) == ALL_PADDINGS) {
} else if (mTouchedSegment >= SEG_PL && mTouchedSegment <= SEG_PB) {
if ((mSelectedSegments & ALL_PADDINGS) == ALL_PADDINGS) {
mSelectedSegments &= ~ALL_PADDINGS;
} else {
mSelectedSegments |= ALL_PADDINGS;
}
} else {
if(mSelectedSegments != 0) {
if (mSelectedSegments != 0) {
mSelectedSegments = 0;
} else {
mSelectedSegments = 0xffffffff;
}
}
mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments);
invalidate();
}
public void setOnBoxEditorEventListener(Object token, OnBoxEditorEventListener listener) {
mOnBoxEditorEventToken = token;
mOnBoxEditorEventListener = listener;
}
mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments);
invalidate();
}
private void drawArea(Canvas canvas, int n) {
Path p = mAreas[n];
if(p != null) {
if((mSelectedSegments & 1<<n)!=0) {
canvas.drawPath(p, mSelectedAreaPaint);
}
}
}
public void setOnBoxEditorEventListener(Object token, OnBoxEditorEventListener listener) {
mOnBoxEditorEventToken = token;
mOnBoxEditorEventListener = listener;
}
private void drawArea(Canvas canvas, int n) {
Path p = mAreas[n];
if (p != null) {
if ((mSelectedSegments & 1 << n) != 0) {
canvas.drawPath(p, mSelectedAreaPaint);
}
}
}
public interface OnBoxEditorEventListener {
void onBoxSelectionChanged(Object token, int selection);
}
}

View file

@ -35,80 +35,79 @@ import net.pierrox.lightning_launcher_extreme.R;
@SuppressWarnings("deprecation")
public class BubbleLayout extends AbsoluteLayout {
private float mDensity;
private final int mBubbleArrowShift;
private float mDensity;
private int mScreenPadding;
private Rect mItemBounds;
private int mBubbleArrowShift;
public BubbleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
private Rect mItemBounds;
public BubbleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mBubbleArrowShift = getContext().getResources().getDimensionPixelSize(R.dimen.bubble_arrow_shift);
}
}
public void setScreenPadding(int padding) {
mScreenPadding = padding;
}
public void setItemBounds(Rect item_bounds) {
mItemBounds = new Rect(item_bounds);
mItemBounds.offset(0, -mScreenPadding);
requestLayout();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(mItemBounds == null) {
return;
}
View bubble = getChildAt(0);
View arrow_down = getChildAt(1);
View arrow_up = getChildAt(2);
final int w = getWidth();
final int h = getHeight();
boolean above = (h-mItemBounds.bottom) < mItemBounds.top;
View arrow;
if(above) {
arrow = arrow_down;
arrow_up.layout(-1, -1, -1, -1);
} else {
arrow = arrow_up;
arrow_down.layout(-1, -1, -1, -1);
}
int b_left, b_right, b_top, b_bottom;
int a_left, a_right, a_top, a_bottom;
final int bw = bubble.getMeasuredWidth();
final int bh = bubble.getMeasuredHeight();
final int aw = arrow.getMeasuredWidth();
final int ah = arrow.getMeasuredHeight();
final int i_center = mItemBounds.centerX();
b_left = i_center - bw/2;
if(b_left<0) b_left=0;
b_right = b_left+bw;
if(b_right>w) {
b_left = w-bw;
b_right = w;
}
a_left = i_center - aw/2;
if(a_left<0) a_left = 0;
a_right = a_left + aw;
if(a_right > w) {
a_left = w - aw;
a_right = w;
}
int shift=Math.round(mDensity*mBubbleArrowShift/1.5f)-1;
public void setItemBounds(Rect item_bounds) {
mItemBounds = new Rect(item_bounds);
mItemBounds.offset(0, -mScreenPadding);
requestLayout();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mItemBounds == null) {
return;
}
View bubble = getChildAt(0);
View arrow_down = getChildAt(1);
View arrow_up = getChildAt(2);
final int w = getWidth();
final int h = getHeight();
boolean above = (h - mItemBounds.bottom) < mItemBounds.top;
View arrow;
if (above) {
arrow = arrow_down;
arrow_up.layout(-1, -1, -1, -1);
} else {
arrow = arrow_up;
arrow_down.layout(-1, -1, -1, -1);
}
int b_left, b_right, b_top, b_bottom;
int a_left, a_right, a_top, a_bottom;
final int bw = bubble.getMeasuredWidth();
final int bh = bubble.getMeasuredHeight();
final int aw = arrow.getMeasuredWidth();
final int ah = arrow.getMeasuredHeight();
final int i_center = mItemBounds.centerX();
b_left = i_center - bw / 2;
if (b_left < 0) b_left = 0;
b_right = b_left + bw;
if (b_right > w) {
b_left = w - bw;
b_right = w;
}
a_left = i_center - aw / 2;
if (a_left < 0) a_left = 0;
a_right = a_left + aw;
if (a_right > w) {
a_left = w - aw;
a_right = w;
}
int shift = Math.round(mDensity * mBubbleArrowShift / 1.5f) - 1;
int anchor_y;
// int max_height_delta = h/3;
@ -116,7 +115,7 @@ public class BubbleLayout extends AbsoluteLayout {
// anchor_y =above ? mItemBounds.top : mItemBounds.bottom;
// } else {
int delta;
if(mItemBounds.height()==0) {
if (mItemBounds.height() == 0) {
delta = 0;
} else {
int mh = mItemBounds.height() / 2;
@ -125,32 +124,32 @@ public class BubbleLayout extends AbsoluteLayout {
anchor_y = mItemBounds.centerY() + (above ? -delta : delta);
// }
if(above) {
// above
b_bottom = anchor_y - ah + shift;
b_top = b_bottom - bh;
a_bottom = anchor_y;
a_top = a_bottom - ah;
} else {
// below
b_top = anchor_y + ah - shift;
b_bottom = b_top + bh;
a_top = anchor_y;
a_bottom = a_top + ah;
}
if(b_top<0) {
b_top=above ? 0 : ah;
int height_diff=bh-(b_bottom-b_top);
if(height_diff>0) {
b_bottom+=height_diff;
a_top+=height_diff;
a_bottom+=height_diff;
}
if(above) {
if (above) {
// above
b_bottom = anchor_y - ah + shift;
b_top = b_bottom - bh;
a_bottom = anchor_y;
a_top = a_bottom - ah;
} else {
// below
b_top = anchor_y + ah - shift;
b_bottom = b_top + bh;
a_top = anchor_y;
a_bottom = a_top + ah;
}
if (b_top < 0) {
b_top = above ? 0 : ah;
int height_diff = bh - (b_bottom - b_top);
if (height_diff > 0) {
b_bottom += height_diff;
a_top += height_diff;
a_bottom += height_diff;
}
if (above) {
int max_height = anchor_y;//h/2-ah;
int height = b_bottom - b_top;
if (height > max_height) {
@ -160,14 +159,14 @@ public class BubbleLayout extends AbsoluteLayout {
a_bottom += height_diff;
}
}
}
if(b_bottom>h) b_bottom=h;
bubble.layout(b_left, b_top, b_right, b_bottom);
arrow.layout(a_left, a_top, a_right, a_bottom);
}
}
if (b_bottom > h) b_bottom = h;
public void setDensity(float density) {
mDensity = density;
}
bubble.layout(b_left, b_top, b_right, b_bottom);
arrow.layout(a_left, a_top, a_right, a_bottom);
}
public void setDensity(float density) {
mDensity = density;
}
}

View file

@ -45,35 +45,29 @@ import android.widget.ImageView;
import net.pierrox.lightning_launcher_extreme.R;
public class CropperView extends ImageView {
public interface OnCropperViewEvent {
public void onCropperViewSelectionChanged(Rect selection);
public void onCropperViewClick();
}
private final Paint mSelectionRectPaint;
private final Paint mOutHighlightPaint;
private final Bitmap mHandleWidthBitmap;
private final Bitmap mHandleHeightBitmap;
private final float mDensity;
private final int mHandleTouchSize;
private final int mTouchSlope;
private final Matrix mTmpMatrix = new Matrix();
RectF mTmpRectF = new RectF();
Rect mTmpRect = new Rect();
private Bitmap mBitmap;
private Rect mSelectionRect;
private Paint mSelectionRectPaint;
private Paint mOutHighlightPaint;
private Bitmap mHandleWidthBitmap;
private Bitmap mHandleHeightBitmap;
private float mDensity;
private int mHandleTouchSize;
private int mTouchSlope;
private boolean mIsDown;
private int mDownX, mDownY;
private int mCurrentMoveArea;
private Rect mInitialSelectionRect;
private long mLastClickDate;
private boolean mMoving;
private OnCropperViewEvent mListener;
private Runnable mClickRunnable = new Runnable() {
private final Runnable mClickRunnable = new Runnable() {
@Override
public void run() {
if(mListener != null) mListener.onCropperViewClick();
if (mListener != null) mListener.onCropperViewClick();
}
};
@ -94,7 +88,7 @@ public class CropperView extends ImageView {
mSelectionRectPaint.setStyle(Paint.Style.STROKE);
mDensity = resources.getDisplayMetrics().density;
mHandleTouchSize = (int)(16*mDensity);
mHandleTouchSize = (int) (16 * mDensity);
mTouchSlope = ViewConfiguration.get(context).getScaledTouchSlop();
}
@ -109,7 +103,7 @@ public class CropperView extends ImageView {
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(w!=0 && h != 0) {
if (w != 0 && h != 0) {
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
Matrix m = new Matrix();
@ -140,8 +134,8 @@ public class CropperView extends ImageView {
final int handleHHeight = mHandleHeightBitmap.getHeight();
canvas.drawBitmap(mHandleWidthBitmap, mSelectionRect.left - handleWWidth / 2, mSelectionRect.centerY() - handleWHeight / 2, null);
canvas.drawBitmap(mHandleWidthBitmap, mSelectionRect.right - handleWWidth / 2, mSelectionRect.centerY() - handleWHeight / 2, null);
canvas.drawBitmap(mHandleHeightBitmap, centerX - handleHWidth /2, mSelectionRect.top- handleHHeight /2, null);
canvas.drawBitmap(mHandleHeightBitmap, centerX - handleHWidth /2, mSelectionRect.bottom- handleHHeight /2, null);
canvas.drawBitmap(mHandleHeightBitmap, centerX - handleHWidth / 2, mSelectionRect.top - handleHHeight / 2, null);
canvas.drawBitmap(mHandleHeightBitmap, centerX - handleHWidth / 2, mSelectionRect.bottom - handleHHeight / 2, null);
}
@Override
@ -155,7 +149,7 @@ public class CropperView extends ImageView {
final int width = getWidth();
final int height = getHeight();
switch(event.getAction()) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
removeCallbacks(mClickRunnable);
mIsDown = true;
@ -164,15 +158,15 @@ public class CropperView extends ImageView {
mDownY = y;
mCurrentMoveArea = Gravity.NO_GRAVITY;
if(mDownX > mSelectionRect.left && mDownX < mSelectionRect.right && Math.abs(mDownY-mSelectionRect.top) < mHandleTouchSize) {
if (mDownX > mSelectionRect.left && mDownX < mSelectionRect.right && Math.abs(mDownY - mSelectionRect.top) < mHandleTouchSize) {
mCurrentMoveArea = Gravity.TOP;
} else if(mDownX > mSelectionRect.left && mDownX < mSelectionRect.right && Math.abs(mDownY-mSelectionRect.bottom) < mHandleTouchSize) {
} else if (mDownX > mSelectionRect.left && mDownX < mSelectionRect.right && Math.abs(mDownY - mSelectionRect.bottom) < mHandleTouchSize) {
mCurrentMoveArea = Gravity.BOTTOM;
} else if (Math.abs(mDownX - mSelectionRect.left) < mHandleTouchSize && mDownY > mSelectionRect.top && mDownY < mSelectionRect.bottom) {
mCurrentMoveArea = Gravity.LEFT;
} else if(Math.abs(mDownX-mSelectionRect.right) < mHandleTouchSize && mDownY > mSelectionRect.top && mDownY < mSelectionRect.bottom) {
} else if (Math.abs(mDownX - mSelectionRect.right) < mHandleTouchSize && mDownY > mSelectionRect.top && mDownY < mSelectionRect.bottom) {
mCurrentMoveArea = Gravity.RIGHT;
} else if(mSelectionRect.contains(mDownX, mDownY)) {
} else if (mSelectionRect.contains(mDownX, mDownY)) {
mCurrentMoveArea = Gravity.CENTER;
}
mInitialSelectionRect = new Rect(mSelectionRect);
@ -231,7 +225,7 @@ public class CropperView extends ImageView {
return true;
case MotionEvent.ACTION_UP:
if(mIsDown) {
if (mIsDown) {
mIsDown = false;
removeCallbacks(mClickRunnable);
if (!mMoving) {
@ -278,37 +272,13 @@ public class CropperView extends ImageView {
mListener = listener;
}
private Matrix mTmpMatrix = new Matrix();
RectF mTmpRectF = new RectF();
Rect mTmpRect = new Rect();
public void setSelection(Rect selection) {
mTmpRectF.set(selection);
mTmpMatrix.set(getImageMatrix());
Drawable drawable = getDrawable();
Bitmap image = ((BitmapDrawable) drawable).getBitmap();
float sx = drawable.getIntrinsicWidth() / (float)image.getWidth();
float sy = drawable.getIntrinsicHeight() / (float)image.getHeight();
mTmpMatrix.preScale(sx, sy);
mTmpMatrix.mapRect(mTmpRectF);
mTmpRectF.round(mSelectionRect);
if(mSelectionRect.left < 0) mSelectionRect.left = 0;
if(mSelectionRect.right > getWidth()) mSelectionRect.right = getWidth();
if(mSelectionRect.top < 0) mSelectionRect.bottom = 0;
if(mSelectionRect.bottom > getHeight()) mSelectionRect.bottom = getHeight();
sendSelectionChangedEvent();
invalidate();
}
public Rect getSelection() {
mTmpRectF.set(mSelectionRect);
getImageMatrix().invert(mTmpMatrix);
Drawable drawable = getDrawable();
Bitmap image = ((BitmapDrawable) drawable).getBitmap();
float sx = image.getWidth() / (float)drawable.getIntrinsicWidth();
float sy = image.getHeight() / (float)drawable.getIntrinsicHeight();
float sx = image.getWidth() / (float) drawable.getIntrinsicWidth();
float sy = image.getHeight() / (float) drawable.getIntrinsicHeight();
mTmpMatrix.postScale(sx, sy);
mTmpMatrix.mapRect(mTmpRectF);
mTmpRectF.round(mTmpRect);
@ -316,9 +286,33 @@ public class CropperView extends ImageView {
return mTmpRect;
}
public void setSelection(Rect selection) {
mTmpRectF.set(selection);
mTmpMatrix.set(getImageMatrix());
Drawable drawable = getDrawable();
Bitmap image = ((BitmapDrawable) drawable).getBitmap();
float sx = drawable.getIntrinsicWidth() / (float) image.getWidth();
float sy = drawable.getIntrinsicHeight() / (float) image.getHeight();
mTmpMatrix.preScale(sx, sy);
mTmpMatrix.mapRect(mTmpRectF);
mTmpRectF.round(mSelectionRect);
if (mSelectionRect.left < 0) mSelectionRect.left = 0;
if (mSelectionRect.right > getWidth()) mSelectionRect.right = getWidth();
if (mSelectionRect.top < 0) mSelectionRect.bottom = 0;
if (mSelectionRect.bottom > getHeight()) mSelectionRect.bottom = getHeight();
sendSelectionChangedEvent();
invalidate();
}
private void sendSelectionChangedEvent() {
if(mListener != null) {
if (mListener != null) {
mListener.onCropperViewSelectionChanged(getSelection());
}
}
public interface OnCropperViewEvent {
void onCropperViewSelectionChanged(Rect selection);
void onCropperViewClick();
}
}

View file

@ -37,9 +37,9 @@ import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher_extreme.R;
public class EditBarHiderView extends ImageButton implements Runnable {
private static final long ANIM_DURATION =200;
private static final long ANIM_DURATION = 200;
private Bitmap mBitmap;
private final Bitmap mBitmap;
private float mAngle;
private Matrix mMatrix;
private long mAnimStart;
@ -64,15 +64,15 @@ public class EditBarHiderView extends ImageButton implements Runnable {
@Override
public void run() {
long delta = AnimationUtils.currentAnimationTimeMillis() - mAnimStart;
if(delta> ANIM_DURATION) {
if (delta > ANIM_DURATION) {
delta = ANIM_DURATION;
}
float angle = 180f*delta / ANIM_DURATION;
if(!mAnimDirection) {
float angle = 180f * delta / ANIM_DURATION;
if (!mAnimDirection) {
angle = 180 - angle;
}
setEditBarHiderRotation(angle);
if(delta == ANIM_DURATION) {
if (delta == ANIM_DURATION) {
mMatrix = null;
} else {
post(this);
@ -87,7 +87,7 @@ public class EditBarHiderView extends ImageButton implements Runnable {
private void updateMatrix() {
int dw = mBitmap.getWidth() / 2;
int dh = mBitmap.getHeight() / 2;
if(mMatrix == null) {
if (mMatrix == null) {
mMatrix = new Matrix();
} else {
mMatrix.reset();
@ -99,7 +99,7 @@ public class EditBarHiderView extends ImageButton implements Runnable {
}
public void setArrowDirection(boolean open) {
if(mAnimDirection != open) {
if (mAnimDirection != open) {
mAnimDirection = open;
removeCallbacks(this);
mAnimStart = AnimationUtils.currentAnimationTimeMillis();

View file

@ -30,38 +30,37 @@ import android.view.KeyEvent;
import android.widget.EditText;
public class EditTextIme extends EditText {
private OnEditTextImeListener mListener;
public interface OnEditTextImeListener {
public void onEditTextImeBackPressed();
}
public EditTextIme(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnEditTextImeListener(OnEditTextImeListener listener) {
mListener = listener;
}
private OnEditTextImeListener mListener;
private boolean mHadKeyDown;
@Override
public boolean onKeyPreIme (int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK) {
switch(event.getAction()) {
public EditTextIme(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnEditTextImeListener(OnEditTextImeListener listener) {
mListener = listener;
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
mHadKeyDown = true;
return false;
case KeyEvent.ACTION_UP:
if(mHadKeyDown && mListener != null) {
if (mHadKeyDown && mListener != null) {
mListener.onEditTextImeBackPressed();
}
mHadKeyDown = false;
return true;
}
}
return false;
}
}
return false;
}
public interface OnEditTextImeListener {
void onEditTextImeBackPressed();
}
}

View file

@ -60,23 +60,14 @@ import java.util.HashSet;
public class HierarchyScreen {
public interface HierarchyScreenListener {
void onHierarchyScreenItemEdit(ContainerPath path, Item item);
void onHierarchyScreenContainerSettings(ContainerPath path);
void onHierarchyScreenItemMoved(HierarchyItem which, HierarchyItem before, HierarchyItem after);
int[] onHierarchyScreenGetRootPages();
}
private LightningEngine mLightningEngine;
private Screen mScreen;
private final LightningEngine mLightningEngine;
private final Screen mScreen;
private final HierarchyScreenListener mListener;
private View mRootView;
private HierarchyScreenListener mListener;
private Animation mHierarchyPaneAnimIn;
private Animation mHierarchyPaneAnimOut;
private DragSortListView mDragSortListView;
private HierarchyAdapter mAdapter;
public HierarchyScreen(LightningEngine engine, Screen screen, HierarchyScreenListener listener) {
mLightningEngine = engine;
mScreen = screen;
@ -84,7 +75,7 @@ public class HierarchyScreen {
}
public void destroy() {
if(mAdapter != null) {
if (mAdapter != null) {
mAdapter.destroy();
}
}
@ -94,15 +85,15 @@ public class HierarchyScreen {
}
public void show(ContainerPath scrollToPath) {
if(mRootView == null) {
if (mRootView == null) {
// setup
final Context context = mScreen.getContext();
mRootView = LayoutInflater.from(context).inflate(R.layout.hierarchy_pane, null);
ViewGroup contentView = mScreen.getContentView();
ViewGroup editControlsView = (ViewGroup) contentView.findViewById(R.id.edit_controls);
ViewGroup editControlsView = contentView.findViewById(R.id.edit_controls);
editControlsView.addView(mRootView); // the dashboard should be responsible for inserting this view in its hierarchy
mDragSortListView = (DragSortListView) mRootView.findViewById(android.R.id.list);
mDragSortListView = mRootView.findViewById(android.R.id.list);
mAdapter = new HierarchyAdapter(context, mDragSortListView);
mHierarchyPaneAnimIn = AnimationUtils.makeInAnimation(context, true);
@ -123,9 +114,9 @@ public class HierarchyScreen {
HierarchyItem which = mAdapter.getItem(from);
if (from == to) {
String name;
if(which.isContainer()) {
if (which.isContainer()) {
Page page = mLightningEngine.getOrLoadPage(which.page);
name = Utils.formatPageName(page, which.parent==null ? null : which.parent.item);
name = Utils.formatPageName(page, which.parent == null ? null : which.parent.item);
} else {
name = Utils.formatItemName(which.item, 0, 0);
}
@ -153,7 +144,6 @@ public class HierarchyScreen {
});
mDragSortListView.setDragListener(new DragSortListView.DragListener() {
@Override
public void drag(int from, int to) {
@ -178,14 +168,14 @@ public class HierarchyScreen {
});
}
if(!isShown()) {
if(scrollToPath != null) {
if (!isShown()) {
if (scrollToPath != null) {
expandPath(scrollToPath);
}
refresh();
if(scrollToPath != null) {
if (scrollToPath != null) {
int pos = 0;
for (HierarchyItem hi : mAdapter.mItems) {
if (hi.isContainer() && hi.path.equals(scrollToPath)) {
@ -203,14 +193,14 @@ public class HierarchyScreen {
private void expandPath(ContainerPath path) {
ContainerPath parent = path.getParent();
if(parent != null) {
if (parent != null) {
expandPath(parent);
}
mAdapter.setExpandedState(path, true);
}
public void hide() {
if(isShown()) {
if (isShown()) {
mRootView.setVisibility(View.GONE);
mRootView.startAnimation(mHierarchyPaneAnimOut);
}
@ -225,9 +215,18 @@ public class HierarchyScreen {
mAdapter.notifyDataSetChanged();
}
public interface HierarchyScreenListener {
void onHierarchyScreenItemEdit(ContainerPath path, Item item);
void onHierarchyScreenContainerSettings(ContainerPath path);
void onHierarchyScreenItemMoved(HierarchyItem which, HierarchyItem before, HierarchyItem after);
int[] onHierarchyScreenGetRootPages();
}
private static class ExpandedPathSet {
private HashSet<String> mExpandedPaths = new HashSet<>();
private final HashSet<String> mExpandedPaths = new HashSet<>();
public boolean add(ContainerPath path) {
return mExpandedPaths.add(path.toString());
@ -242,20 +241,20 @@ public class HierarchyScreen {
}
}
public static class HierarchyPath extends ContainerPath{
public static class HierarchyPath extends ContainerPath {
public HierarchyPath(HierarchyItem item) {
super((String)null);
super((String) null);
StringBuilder path = new StringBuilder();
build(item, path);
mPath = path.toString();
}
private void build(HierarchyItem item, StringBuilder out) {
if(item.parent != null) {
if (item.parent != null) {
build(item.parent, out);
out.append('/');
}
if(item.item == null) {
if (item.item == null) {
out.append(item.page);
} else {
out.append(item.item.getId());
@ -276,6 +275,7 @@ public class HierarchyScreen {
this.page = page;
this.path = new HierarchyPath(this);
}
public HierarchyItem(HierarchyItem parent, int level, int page, Item item) {
this.parent = parent;
this.level = level;
@ -283,20 +283,21 @@ public class HierarchyScreen {
this.item = item;
this.path = new HierarchyPath(this);
}
public boolean isContainer() {
return item == null || item instanceof Folder;
}
public int getContainerId() {
if(item == null) {
if (item == null) {
return page;
} else {
return ((Folder)item).getFolderPageId();
return ((Folder) item).getFolderPageId();
}
}
public int getParentContainerId() {
if(item == null) {
if (item == null) {
return Page.NONE;
} else {
return Utils.getPageForItem(item);
@ -305,16 +306,22 @@ public class HierarchyScreen {
}
private class HierarchyAdapter extends BaseAdapter implements View.OnClickListener, View.OnLongClickListener {
private Context mContext;
private ListView mHostListView;
private LightningEngine.PageManager mPageManager;
private final Context mContext;
private final ListView mHostListView;
private final LightningEngine.PageManager mPageManager;
private final ExpandedPathSet mExpandedPaths;
private final int mIndent;
private final Page.PageListener mPageListener = new Page.EmptyPageListener() {
@Override
public void onPageRemoved(Page page) {
// TODO handle removals
}
@Override
public void onPageLoaded(Page page) {
}
};
private ArrayList<HierarchyItem> mItems;
private ExpandedPathSet mExpandedPaths;
private int mIndent;
private int mHoveredItem = -1;
public HierarchyAdapter(Context context, ListView hostListView) {
@ -362,16 +369,16 @@ public class HierarchyScreen {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.hierarchy_item, parent, false);
Button containerSettingsButton = (Button) convertView.findViewById(R.id.eb_cs);
Button containerSettingsButton = convertView.findViewById(R.id.eb_cs);
containerSettingsButton.setTypeface(LLApp.get().getIconsTypeface());
containerSettingsButton.setOnClickListener(this);
containerSettingsButton.setOnLongClickListener(this);
containerSettingsButton.setContentDescription(mContext.getString(R.string.mi_es_settings));
Button editButton = (Button) convertView.findViewById(R.id.eb_edit);
Button editButton = convertView.findViewById(R.id.eb_edit);
editButton.setTypeface(LLApp.get().getIconsTypeface());
editButton.setOnClickListener(this);
editButton.setOnLongClickListener(this);
@ -379,15 +386,15 @@ public class HierarchyScreen {
}
HierarchyItem hi = getItem(position);
TextView textView = (TextView) convertView.findViewById(R.id.label);
TextView textView = convertView.findViewById(R.id.label);
Page page = mLightningEngine.getOrLoadPage(hi.page);
CharSequence label;
if(hi.item == null) {
label = Utils.formatPageName(page, hi.parent==null ? null : hi.parent.item);
if (hi.item == null) {
label = Utils.formatPageName(page, hi.parent == null ? null : hi.parent.item);
} else {
label = Utils.formatItemName(hi.item, 0, 0);
}
if(hi.isContainer()) {
if (hi.isContainer()) {
SpannableString spannedLabel = new SpannableString(label);
spannedLabel.setSpan(new StyleSpan(Typeface.BOLD), 0, label.length(), 0);
label = spannedLabel;
@ -395,18 +402,18 @@ public class HierarchyScreen {
textView.setText(label);
textView.setPadding(hi.level * mIndent, 0, 0, 0);
Button containerSettingsButton = (Button) convertView.findViewById(R.id.eb_cs);
Button containerSettingsButton = convertView.findViewById(R.id.eb_cs);
containerSettingsButton.setTag(hi);
containerSettingsButton.setVisibility(hi.isContainer() ? View.VISIBLE : View.INVISIBLE);
Button editButton = (Button) convertView.findViewById(R.id.eb_edit);
Button editButton = convertView.findViewById(R.id.eb_edit);
editButton.setTag(hi);
return convertView;
}
public void setExpandedState(ContainerPath item, boolean expanded) {
if(expanded) {
if (expanded) {
mExpandedPaths.add(item);
} else {
mExpandedPaths.remove(item);
@ -414,7 +421,7 @@ public class HierarchyScreen {
}
public void toggleExpandedState(ContainerPath path) {
if(mExpandedPaths.contains(path)) {
if (mExpandedPaths.contains(path)) {
mExpandedPaths.remove(path);
} else {
mExpandedPaths.add(path);
@ -423,12 +430,16 @@ public class HierarchyScreen {
notifyDataSetChanged();
}
public int getHoveredItem() {
return mHoveredItem;
}
public void setHoveredItem(int position) {
if (mHoveredItem != position) {
if(mHoveredItem != -1) {
if (mHoveredItem != -1) {
setItemHoveredState(mHoveredItem, false);
}
if(position != -1 && getItem(position).isContainer()) {
if (position != -1 && getItem(position).isContainer()) {
mHoveredItem = position;
setItemHoveredState(mHoveredItem, true);
} else {
@ -437,10 +448,6 @@ public class HierarchyScreen {
}
}
public int getHoveredItem() {
return mHoveredItem;
}
private void setItemHoveredState(int position, boolean hovered) {
View view = mHostListView.getChildAt(position - mHostListView.getFirstVisiblePosition());
if (view != null) {
@ -453,7 +460,7 @@ public class HierarchyScreen {
mItems = new ArrayList<>();
int[] pages = mListener.onHierarchyScreenGetRootPages();
for(int page : pages) {
for (int page : pages) {
HierarchyItem desktopHierarchyItem = new HierarchyItem(null, 0, page);
mItems.add(desktopHierarchyItem);
addPageItems(desktopHierarchyItem, page, 1);
@ -461,7 +468,7 @@ public class HierarchyScreen {
}
private void addPageItems(HierarchyItem parent, int page, int level) {
if(!mExpandedPaths.contains(parent.path)) {
if (!mExpandedPaths.contains(parent.path)) {
return;
}
@ -469,7 +476,7 @@ public class HierarchyScreen {
for (Item item : p.items) {
HierarchyItem hierarchyItem = new HierarchyItem(parent, level, page, item);
mItems.add(hierarchyItem);
if(item instanceof Folder) {
if (item instanceof Folder) {
Folder folder = (Folder) item;
addPageItems(hierarchyItem, folder.getFolderPageId(), level + 1);
}
@ -480,8 +487,12 @@ public class HierarchyScreen {
public void onClick(View v) {
HierarchyItem hi = (HierarchyItem) v.getTag();
switch (v.getId()) {
case R.id.eb_edit: mListener.onHierarchyScreenItemEdit(hi.path, hi.item); break;
case R.id.eb_cs: mListener.onHierarchyScreenContainerSettings(new HierarchyPath(hi)); break;
case R.id.eb_edit:
mListener.onHierarchyScreenItemEdit(hi.path, hi.item);
break;
case R.id.eb_cs:
mListener.onHierarchyScreenContainerSettings(new HierarchyPath(hi));
break;
}
}
@ -489,28 +500,21 @@ public class HierarchyScreen {
public boolean onLongClick(View v) {
int label_res = 0;
switch (v.getId()) {
case R.id.eb_edit: label_res = R.string.hs_ed; break;
case R.id.eb_cs: label_res = R.string.mi_es_settings; break;
case R.id.eb_edit:
label_res = R.string.hs_ed;
break;
case R.id.eb_cs:
label_res = R.string.mi_es_settings;
break;
}
if(label_res != 0) {
if (label_res != 0) {
int[] location = new int[2];
v.getLocationOnScreen(location);
Toast toast = Toast.makeText(mContext, label_res, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP|Gravity.LEFT, location[0], location[1]);
toast.setGravity(Gravity.TOP | Gravity.LEFT, location[0], location[1]);
toast.show();
}
return true;
}
private Page.PageListener mPageListener = new Page.EmptyPageListener() {
@Override
public void onPageRemoved(Page page) {
// TODO handle removals
}
@Override
public void onPageLoaded(Page page) {
}
};
}
}

View file

@ -24,8 +24,6 @@ SOFTWARE.
package net.pierrox.lightning_launcher.views;
import java.util.ArrayList;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
@ -35,76 +33,28 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
import java.util.ArrayList;
public class MyViewPager extends ViewGroup {
/**
* Callback interface for responding to changing state of the selected page.
*/
public interface OnPageChangeListener {
/**
* This method will be invoked when the current page is scrolled, either as part
* of a programmatically initiated smooth scroll or a user initiated touch scroll.
*
* @param position Position index of the first page currently being displayed.
* Page position+1 will be visible if positionOffset is nonzero.
* @param positionOffset Value from [0, 1) indicating the offset from the page at position.
* @param positionOffsetPixels Value in pixels indicating the offset from position.
*/
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
/**
* This method will be invoked when a new page becomes selected. Animation is not
* necessarily complete.
*
* @param position Position index of the new selected page.
*/
public void onPageSelected(int position);
/**
* Called when the scroll state changes. Useful for discovering when the user
* begins dragging, when the pager is automatically settling to the current page,
* or when it is fully stopped/idle.
*
* @param state The new scroll state.
* @see ViewPager#SCROLL_STATE_IDLE
* @see ViewPager#SCROLL_STATE_DRAGGING
* @see ViewPager#SCROLL_STATE_SETTLING
*/
public void onPageScrollStateChanged(int state);
}
/**
* Indicates that the pager is in an idle, settled state. The current page
* is fully in view and no animation is in progress.
*/
public static final int SCROLL_STATE_IDLE = 0;
/**
* Indicates that the pager is currently being dragged by the user.
*/
public static final int SCROLL_STATE_DRAGGING = 1;
/**
* Indicates that the pager is in the process of settling to a final position.
*/
public static final int SCROLL_STATE_SETTLING = 2;
protected static class ItemInfo {
View v;
int position;
boolean scrolling;
}
protected final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>(2);
private OnPageChangeListener mOnPageChangeListener;
private int mScrollState = SCROLL_STATE_IDLE;
private Scroller mScroller;
private int mCurItem;
private boolean mScrolling;
private int mChildWidthMeasureSpec;
private int mChildHeightMeasureSpec;
private boolean mIsBeingDragged;
@ -113,22 +63,20 @@ public class MyViewPager extends ViewGroup {
private float mInitialMotionX;
private float mLastMotionX;
private float mLastMotionY;
private VelocityTracker mVelocityTracker;
private int mMinimumVelocity;
private int mMaximumVelocity;
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initViewPager();
}
@Override
protected void onFinishInflate() {
initPagerItems();
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initViewPager();
}
@Override
protected void onFinishInflate() {
initPagerItems();
}
@Override
public void removeViewAt(int index) {
@ -138,11 +86,11 @@ public class MyViewPager extends ViewGroup {
protected void initPagerItems() {
mItems.clear();
int n=getChildCount();
int n = getChildCount();
int index = 0;
for(int i=0; i<n; i++) {
for (int i = 0; i < n; i++) {
View view = getChildAt(i);
if(view.getVisibility() == VISIBLE) {
if (view.getVisibility() == VISIBLE) {
ItemInfo ii = new ItemInfo();
ii.v = view;
ii.position = index++;
@ -151,14 +99,13 @@ public class MyViewPager extends ViewGroup {
}
}
int size = mItems.size() - 1;
if(mCurItem > size) {
if (mCurItem > size) {
setCurrentItemInternal(size, false, true);
}
requestLayout();
}
@Override
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// For simple implementation, or internal size is always 0.
// We depend on the container to specify the layout size of
@ -189,23 +136,23 @@ public class MyViewPager extends ViewGroup {
super.onSizeChanged(w, h, oldw, oldh);
// Make sure scroll position is set correctly.
int scrollPos = mCurItem*w;
int scrollPos = mCurItem * w;
if (scrollPos != getScrollX()) {
completeScroll();
scrollTo(scrollPos, getScrollY());
}
}
@Override
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
final int width = r-l;
final int width = r - l;
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
ItemInfo ii;
if (child.getVisibility() != GONE && (ii=infoForChild(child)) != null) {
int loff = width*ii.position;
if (child.getVisibility() != GONE && (ii = infoForChild(child)) != null) {
int loff = width * ii.position;
int childLeft = getPaddingLeft() + loff;
int childTop = getPaddingTop();
child.layout(childLeft, childTop,
@ -214,8 +161,8 @@ public class MyViewPager extends ViewGroup {
}
}
}
@Override
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* This method JUST determines whether we want to intercept the motion.
@ -252,7 +199,6 @@ public class MyViewPager extends ViewGroup {
*/
final float x = ev.getX();
final float dx = x - mLastMotionX;
final float xDiff = Math.abs(dx);
@ -299,9 +245,9 @@ public class MyViewPager extends ViewGroup {
}
/*
* The only time we want to intercept motion events is if we are in the
* drag mode.
*/
* The only time we want to intercept motion events is if we are in the
* drag mode.
*/
return mIsBeingDragged;
}
@ -377,13 +323,13 @@ public class MyViewPager extends ViewGroup {
if (mIsBeingDragged) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int)velocityTracker.getYVelocity();
int initialVelocity = (int) velocityTracker.getYVelocity();
if ((Math.abs(initialVelocity) > mMinimumVelocity)
|| Math.abs(mInitialMotionX-mLastMotionX) >= (getWidth()/3)) {
|| Math.abs(mInitialMotionX - mLastMotionX) >= (getWidth() / 3)) {
if (mLastMotionX > mInitialMotionX) {
setCurrentItemInternal(mCurItem-1, true, true);
setCurrentItemInternal(mCurItem - 1, true, true);
} else {
setCurrentItemInternal(mCurItem+1, true, true);
setCurrentItemInternal(mCurItem + 1, true, true);
}
} else {
setCurrentItemInternal(mCurItem, true, true);
@ -401,7 +347,7 @@ public class MyViewPager extends ViewGroup {
}
return true;
}
@Override
public void computeScroll() {
if (!mScroller.isFinished()) {
@ -432,40 +378,40 @@ public class MyViewPager extends ViewGroup {
// Done with scroll, clean up state.
completeScroll();
}
public void setOnPageChangeListener(OnPageChangeListener listener) {
mOnPageChangeListener = listener;
}
public int getCurrentItem() {
return mCurItem;
}
public void setCurrentItem(int item) {
setCurrentItemInternal(item, true, false);
}
public View getCurrentView() {
return mItems.get(mCurItem).v;
}
public void setCurrentView(View v) {
for(ItemInfo ii : mItems) {
if(ii.v == v) {
for (ItemInfo ii : mItems) {
if (ii.v == v) {
setCurrentItemInternal(ii.position, false, false);
break;
}
}
}
public int getCurrentItem() {
return mCurItem;
}
public View getCurrentView() {
return mItems.get(mCurItem).v;
}
public boolean isFirst() {
return mCurItem == 0;
}
public boolean isLast() {
return mCurItem == mItems.size()-1;
return mCurItem == mItems.size() - 1;
}
private void endDrag() {
mIsBeingDragged = false;
mIsUnableToDrag = false;
@ -475,7 +421,7 @@ public class MyViewPager extends ViewGroup {
mVelocityTracker = null;
}
}
private void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {
if (!always && mCurItem == item && mItems.size() != 0) {
return;
@ -488,18 +434,18 @@ public class MyViewPager extends ViewGroup {
item = size;
}
}
if (item > (mCurItem+1) || item < (mCurItem-1)) {
if (item > (mCurItem + 1) || item < (mCurItem - 1)) {
// We are doing a jump by more than one page. To avoid
// glitches, we want to keep all current pages in the view
// until the scroll ends.
for (int i=0; i<mItems.size(); i++) {
for (int i = 0; i < mItems.size(); i++) {
mItems.get(i).scrolling = true;
}
}
final boolean dispatchSelected = mCurItem != item;
mCurItem = item;
if (smoothScroll) {
smoothScrollTo(getWidth()*item, 0);
smoothScrollTo(getWidth() * item, 0);
if (dispatchSelected && mOnPageChangeListener != null) {
mOnPageChangeListener.onPageSelected(item);
}
@ -508,11 +454,11 @@ public class MyViewPager extends ViewGroup {
mOnPageChangeListener.onPageSelected(item);
}
completeScroll();
scrollTo(getWidth()*item, 0);
scrollTo(getWidth() * item, 0);
}
}
private void initViewPager() {
private void initViewPager() {
setWillNotDraw(false);
mScroller = new Scroller(getContext());
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
@ -521,13 +467,13 @@ public class MyViewPager extends ViewGroup {
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
}
private ItemInfo infoForChild(View child) {
for(ItemInfo ii : mItems) {
if(ii.v == child) return ii;
}
private ItemInfo infoForChild(View child) {
for (ItemInfo ii : mItems) {
if (ii.v == child) return ii;
}
return null;
}
/**
* Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
*
@ -553,8 +499,8 @@ public class MyViewPager extends ViewGroup {
mScroller.startScroll(sx, sy, dx, dy);
invalidate();
}
private void completeScroll() {
private void completeScroll() {
if (mScrolling) {
// Done with scroll, no longer want to cache view drawing.
mScroller.abortAnimation();
@ -568,15 +514,15 @@ public class MyViewPager extends ViewGroup {
setScrollState(SCROLL_STATE_IDLE);
}
mScrolling = false;
for (int i=0; i<mItems.size(); i++) {
for (int i = 0; i < mItems.size(); i++) {
ItemInfo ii = mItems.get(i);
if (ii.scrolling) {
ii.scrolling = false;
}
}
}
private void setScrollState(int newState) {
private void setScrollState(int newState) {
if (mScrollState == newState) {
return;
}
@ -586,4 +532,47 @@ public class MyViewPager extends ViewGroup {
mOnPageChangeListener.onPageScrollStateChanged(newState);
}
}
/**
* Callback interface for responding to changing state of the selected page.
*/
public interface OnPageChangeListener {
/**
* This method will be invoked when the current page is scrolled, either as part
* of a programmatically initiated smooth scroll or a user initiated touch scroll.
*
* @param position Position index of the first page currently being displayed.
* Page position+1 will be visible if positionOffset is nonzero.
* @param positionOffset Value from [0, 1) indicating the offset from the page at position.
* @param positionOffsetPixels Value in pixels indicating the offset from position.
*/
void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
/**
* This method will be invoked when a new page becomes selected. Animation is not
* necessarily complete.
*
* @param position Position index of the new selected page.
*/
void onPageSelected(int position);
/**
* Called when the scroll state changes. Useful for discovering when the user
* begins dragging, when the pager is automatically settling to the current page,
* or when it is fully stopped/idle.
*
* @param state The new scroll state.
* @see ViewPager#SCROLL_STATE_IDLE
* @see ViewPager#SCROLL_STATE_DRAGGING
* @see ViewPager#SCROLL_STATE_SETTLING
*/
void onPageScrollStateChanged(int state);
}
protected static class ItemInfo {
View v;
int position;
boolean scrolling;
}
}

View file

@ -36,8 +36,8 @@ import net.pierrox.lightning_launcher.views.item.ItemView;
import java.util.ArrayList;
/**
* Created by pierrot on 18/03/2015.
*/
* Created by pierrot on 18/03/2015.
*/
public class SnappingContext {
public static final int SNAP_LEFT = 1;
public static final int SNAP_RIGHT = 2;
@ -46,16 +46,16 @@ public class SnappingContext {
public static final int SNAP_CENTER = 16;
public static final int SNAP_ALL = 31;
private int snap_what;
private float touch_slop;
private final int snap_what;
private final float touch_slop;
private final ItemView my_item_view;
public float min_dx = Float.MAX_VALUE;
public float min_dy = Float.MAX_VALUE;
public float anchor_x = Float.MAX_VALUE;
public float anchor_y = Float.MAX_VALUE;
public ItemLayout item_layout;
private ArrayList<ItemView> snapped_items;
private ArrayList<RectF> snapped_bounds;
private ItemView my_item_view;
public ItemLayout item_layout;
public SnappingContext(ItemView my_item_view, float touch_slop, int snap_what) {
this.my_item_view = my_item_view;
@ -67,7 +67,7 @@ public class SnappingContext {
}
public void stop() {
for(ItemView i : snapped_items) {
for (ItemView i : snapped_items) {
i.setFocused(false);
}
my_item_view.setFocused(false);
@ -79,7 +79,7 @@ public class SnappingContext {
public void computeSnaps(Matrix item_transform) {
Rect hr = new Rect();
item_layout.getHitRect(hr);
RectF screen_bounds=new RectF(hr);
RectF screen_bounds = new RectF(hr);
// compute corners and center of the moving item
RectF bounds_from = new RectF();
@ -87,7 +87,7 @@ public class SnappingContext {
computeItemViewSnapBounds(my_item_view, item_transform, bounds_from);
for(ItemView i : snapped_items) {
for (ItemView i : snapped_items) {
i.setFocused(false);
}
my_item_view.setFocused(false);
@ -100,9 +100,9 @@ public class SnappingContext {
snapped_bounds.clear();
// first pass to compute the minimum distance
for(int n=item_layout.getChildCount()-1; n>=0; n--) {
for (int n = item_layout.getChildCount() - 1; n >= 0; n--) {
View v = item_layout.getChildAt(n);
if(v instanceof ItemView) {
if (v instanceof ItemView) {
ItemView i = (ItemView) v;
if (i.isSelected() || i == my_item_view) continue;
@ -117,9 +117,9 @@ public class SnappingContext {
}
// second pass to find item snapping with the minimum distance
for(int n=item_layout.getChildCount()-1; n>=0; n--) {
for (int n = item_layout.getChildCount() - 1; n >= 0; n--) {
View v = item_layout.getChildAt(n);
if(v instanceof ItemView) {
if (v instanceof ItemView) {
ItemView i = (ItemView) v;
if (i.isSelected() || i == my_item_view) continue;
@ -136,7 +136,7 @@ public class SnappingContext {
}
}
for(ItemView i : snapped_items) {
for (ItemView i : snapped_items) {
i.setFocused(true);
}
}
@ -144,7 +144,7 @@ public class SnappingContext {
public void applySnaps(Matrix item_transform) {
item_layout.setSnappingData(anchor_x, anchor_y, snapped_bounds);
if(snapped_bounds.size() > 0) {
if (snapped_bounds.size() > 0) {
RectF bounds_to = new RectF();
computeItemViewSnapBounds(my_item_view, item_transform, bounds_to);
snapped_bounds.add(bounds_to);
@ -156,7 +156,7 @@ public class SnappingContext {
Item item = itemView.getItem();
float cw = item_layout.getCellWidth();
float ch = item_layout.getCellHeight();
if(item.getItemConfig().onGrid) {
if (item.getItemConfig().onGrid) {
outBounds.set(item.getCell());
outBounds.left *= cw;
outBounds.right *= cw;
@ -166,34 +166,34 @@ public class SnappingContext {
outBounds.set(0, 0, item.getViewWidth(), item.getViewHeight());
itemTransform.mapRect(outBounds);
}
Matrix t=item_layout.getTransformForItemView(itemView);
if(t!=null) {
Matrix t = item_layout.getTransformForItemView(itemView);
if (t != null) {
t.mapRect(outBounds);
}
if(item.getClass() == StopPoint.class) {
outBounds.offset(-outBounds.width()/2, -outBounds.height()/2);
if (item.getClass() == StopPoint.class) {
outBounds.offset(-outBounds.width() / 2, -outBounds.height() / 2);
}
}
private boolean checkSnap(RectF from, RectF to) {
boolean snap = false;
if((snap_what&SNAP_LEFT)!=0) {
if ((snap_what & SNAP_LEFT) != 0) {
snap |= doesSnapX(from.left, to.left);
snap |= doesSnapX(from.left, to.right);
}
if((snap_what&SNAP_RIGHT)!=0) {
if ((snap_what & SNAP_RIGHT) != 0) {
snap |= doesSnapX(from.right, to.right);
snap |= doesSnapX(from.right, to.left);
}
if((snap_what&SNAP_CENTER)!=0) {
if ((snap_what & SNAP_CENTER) != 0) {
snap |= doesSnapX(from.centerX(), to.centerX());
snap |= doesSnapY(from.centerY(), to.centerY());
}
if((snap_what&SNAP_TOP)!=0) {
if ((snap_what & SNAP_TOP) != 0) {
snap |= doesSnapY(from.top, to.top);
snap |= doesSnapY(from.top, to.bottom);
}
if((snap_what&SNAP_BOTTOM)!=0) {
if ((snap_what & SNAP_BOTTOM) != 0) {
snap |= doesSnapY(from.bottom, to.bottom);
snap |= doesSnapY(from.bottom, to.top);
}
@ -202,9 +202,9 @@ public class SnappingContext {
}
private boolean doesSnapX(float from, float to) {
float diff = to-from;
float diff = to - from;
float abs_diff = Math.abs(diff);
if(abs_diff<touch_slop && abs_diff<=Math.abs(min_dx)) {
if (abs_diff < touch_slop && abs_diff <= Math.abs(min_dx)) {
min_dx = diff;
anchor_x = to;
return true;
@ -214,9 +214,9 @@ public class SnappingContext {
}
private boolean doesSnapY(float from, float to) {
float diff = to-from;
float diff = to - from;
float abs_diff = Math.abs(diff);
if(abs_diff<touch_slop && abs_diff<=Math.abs(min_dy)) {
if (abs_diff < touch_slop && abs_diff <= Math.abs(min_dy)) {
min_dy = diff;
anchor_y = to;
return true;

View file

@ -38,9 +38,8 @@ import net.pierrox.lightning_launcher.R;
/**
* Class to manage status and navigation bar tint effects when using KitKat
* Class to manage status and navigation bar tint effects when using KitKat
* translucent system UI modes.
*
*/
public class SystemBarTintManager {
@ -66,18 +65,17 @@ public class SystemBarTintManager {
* The default system bar tint color value.
*/
public static final int DEFAULT_TINT_COLOR = 0x99000000;
private static boolean sGlobalStatusBarTintEnabled = false;
private final boolean mStatusBarAvailable = true;
private final boolean mNavBarAvailable = true;
private final Animation mStatusBarAnimEnter;
private final Animation mStatusBarAnimExit;
private SystemBarConfig mConfig;
private boolean mStatusBarAvailable = true;
private boolean mNavBarAvailable = true;
private boolean mStatusBarTintEnabled;
private boolean mNavBarTintEnabled;
private View mStatusBarTintView;
private View mNavBarTintView;
private Animation mStatusBarAnimEnter;
private Animation mStatusBarAnimExit;
/**
* Constructor. Call this in the host activity onCreate method after its
* content view has been set. You should always create new instances when
@ -105,33 +103,9 @@ public class SystemBarTintManager {
setupNavBarLayoutParams();
}
private static boolean sGlobalStatusBarTintEnabled = false;
/**
* Enable tinting of the system status bar.
*
* If the platform is running Jelly Bean or earlier, or translucent system
* UI modes have not been enabled in either the theme or via window flags,
* then this method does nothing.
*
* @param enabled True to enable tinting, false to disable it (default).
*/
public void setStatusBarTintEnabled(boolean enabled) {
mStatusBarTintEnabled = enabled;
if (mStatusBarAvailable) {
int visibility = enabled ? View.VISIBLE : View.GONE;
if(mStatusBarTintView.getVisibility() != visibility) {
mStatusBarTintView.setVisibility(visibility);
if(mStatusBarTintEnabled != sGlobalStatusBarTintEnabled) {
mStatusBarTintView.startAnimation(enabled ? mStatusBarAnimEnter : mStatusBarAnimExit);
sGlobalStatusBarTintEnabled = mStatusBarTintEnabled;
}
}
}
}
/**
* Enable tinting of the system navigation bar.
*
* <p>
* If the platform does not have soft navigation keys, is running Jelly Bean
* or earlier, or translucent system UI modes have not been enabled in either
* the theme or via window flags, then this method does nothing.
@ -295,6 +269,29 @@ public class SystemBarTintManager {
return mStatusBarTintEnabled;
}
/**
* Enable tinting of the system status bar.
* <p>
* If the platform is running Jelly Bean or earlier, or translucent system
* UI modes have not been enabled in either the theme or via window flags,
* then this method does nothing.
*
* @param enabled True to enable tinting, false to disable it (default).
*/
public void setStatusBarTintEnabled(boolean enabled) {
mStatusBarTintEnabled = enabled;
if (mStatusBarAvailable) {
int visibility = enabled ? View.VISIBLE : View.GONE;
if (mStatusBarTintView.getVisibility() != visibility) {
mStatusBarTintView.setVisibility(visibility);
if (mStatusBarTintEnabled != sGlobalStatusBarTintEnabled) {
mStatusBarTintView.startAnimation(enabled ? mStatusBarAnimEnter : mStatusBarAnimExit);
sGlobalStatusBarTintEnabled = mStatusBarTintEnabled;
}
}
}
}
/**
* Is tinting enabled for the system navigation bar?
*
@ -342,7 +339,6 @@ public class SystemBarTintManager {
/**
* Class which describes system bar sizing and other characteristics for the current
* device configuration.
*
*/
public static class SystemBarConfig {
@ -351,22 +347,20 @@ public class SystemBarTintManager {
// private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
// private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
// private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
// These values are kept in order to be reused when the window insets are not available. This
// is the case when the view is not attached to the window. Also, display cutouts are never
// available in the context of the overlay desktop. Display cutouts are not supposed to change
// so it should be safe enough.
private static int sSafeInsetWidth = 0;
private static int sSafeInsetHeight = 0;
private final boolean mIsInPortrait;
private final int mStatusBarHeight;
private final int mActionBarHeight;
private final boolean mHasNavigationBar;
private final int mNavigationBarHeight;
// private final int mNavigationBarWidth;
// private final int mNavigationBarWidth;
private final boolean mIsNavigationAtBottom;
// These values are kept in order to be reused when the window insets are not available. This
// is the case when the view is not attached to the window. Also, display cutouts are never
// available in the context of the overlay desktop. Display cutouts are not supposed to change
// so it should be safe enough.
private static int sSafeInsetWidth = 0;
private static int sSafeInsetHeight = 0;
private SystemBarConfig(Window window) {
Resources res = window.getContext().getResources();
@ -387,16 +381,16 @@ public class SystemBarTintManager {
if (Build.VERSION.SDK_INT >= 28) {
WindowInsets windowInsets = window.getDecorView().getRootWindowInsets();
if(windowInsets != null) {
if (windowInsets != null) {
DisplayCutout cutout = windowInsets.getDisplayCutout();
if(cutout != null) {
if (cutout != null) {
sSafeInsetWidth = cutout.getSafeInsetLeft() + cutout.getSafeInsetRight();
sSafeInsetHeight = cutout.getSafeInsetTop() + cutout.getSafeInsetBottom();
}
}
}
mIsNavigationAtBottom = realDm.widthPixels == dm.widthPixels;
if(mIsInPortrait || mIsNavigationAtBottom) {
if (mIsInPortrait || mIsNavigationAtBottom) {
mNavigationBarHeight = realDm.heightPixels - dm.heightPixels - sSafeInsetHeight;
} else {
mNavigationBarHeight = realDm.widthPixels - dm.widthPixels - sSafeInsetWidth;

View file

@ -13,11 +13,6 @@
package net.dinglisch.android.tasker;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@ -30,420 +25,406 @@ import android.os.PatternMatcher;
import android.os.Process;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TaskerIntent extends Intent {
// 3 Tasker versions
public final static String TASKER_PACKAGE = "net.dinglisch.android.tasker";
public final static String TASKER_PACKAGE_MARKET = TASKER_PACKAGE + "m";
public final static String TASKER_PACKAGE_CUPCAKE = TASKER_PACKAGE + "cupcake";
// Play Store download URLs
public final static String MARKET_DOWNLOAD_URL_PREFIX = "market://details?id=";
private final static String TASKER_MARKET_URL = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_MARKET;
private final static String TASKER_MARKET_URL_CUPCAKE = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_CUPCAKE;
// Direct-purchase version
private final static String TASKER_DOWNLOAD_URL = "http://tasker.dinglisch.net/download.html";
// Intent actions
public final static String ACTION_TASK = TASKER_PACKAGE + ".ACTION_TASK";
public final static String ACTION_TASK_COMPLETE = TASKER_PACKAGE + ".ACTION_TASK_COMPLETE";
public final static String ACTION_TASK_SELECT = TASKER_PACKAGE + ".ACTION_TASK_SELECT";
// Intent parameters
public final static String EXTRA_ACTION_INDEX_PREFIX = "action";
public final static String TASK_NAME_DATA_SCHEME = "task";
public final static String EXTRA_TASK_NAME = "task_name";
public final static String EXTRA_TASK_PRIORITY = "task_priority";
public final static String EXTRA_SUCCESS_FLAG = "success";
public final static String EXTRA_VAR_NAMES_LIST = "varNames";
public final static String EXTRA_VAR_VALUES_LIST = "varValues";
public final static String EXTRA_TASK_OUTPUT = "output";
// 3 Tasker versions
public final static String TASKER_PACKAGE = "net.dinglisch.android.tasker";
public final static String TASKER_PACKAGE_MARKET = TASKER_PACKAGE + "m";
// Play Store download URLs
public final static String MARKET_DOWNLOAD_URL_PREFIX = "market://details?id=";
private final static String TASKER_MARKET_URL = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_MARKET;
public final static String TASKER_PACKAGE_CUPCAKE = TASKER_PACKAGE + "cupcake";
private final static String TASKER_MARKET_URL_CUPCAKE = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_CUPCAKE;
// Content provider columns
public static final String PROVIDER_COL_NAME_EXTERNAL_ACCESS = "ext_access";
public static final String PROVIDER_COL_NAME_ENABLED = "enabled";
// DEPRECATED, use EXTRA_VAR_NAMES_LIST, EXTRA_VAR_VALUES_LIST
public final static String EXTRA_PARAM_LIST = "params";
// Intent actions
public final static String ACTION_TASK = TASKER_PACKAGE + ".ACTION_TASK";
public final static String ACTION_TASK_COMPLETE = TASKER_PACKAGE + ".ACTION_TASK_COMPLETE";
public final static String ACTION_TASK_SELECT = TASKER_PACKAGE + ".ACTION_TASK_SELECT";
// Intent parameters
public final static String EXTRA_ACTION_INDEX_PREFIX = "action";
public final static String TASK_NAME_DATA_SCHEME = "task";
public final static String EXTRA_TASK_NAME = "task_name";
public final static String EXTRA_TASK_PRIORITY = "task_priority";
public final static String EXTRA_SUCCESS_FLAG = "success";
public final static String EXTRA_VAR_NAMES_LIST = "varNames";
public final static String EXTRA_VAR_VALUES_LIST = "varValues";
public final static String EXTRA_TASK_OUTPUT = "output";
// Content provider columns
public static final String PROVIDER_COL_NAME_EXTERNAL_ACCESS = "ext_access";
public static final String PROVIDER_COL_NAME_ENABLED = "enabled";
// DEPRECATED, use EXTRA_VAR_NAMES_LIST, EXTRA_VAR_VALUES_LIST
public final static String EXTRA_PARAM_LIST = "params";
public final static String TASK_ID_SCHEME = "id";
// Intent data
public final static String TASK_ID_SCHEME = "id";
// For particular actions
public final static String DEFAULT_ENCRYPTION_KEY= "default";
public final static String ENCRYPTED_AFFIX = "tec";
public final static int MAX_NO_ARGS = 10;
// Bundle keys
// Only useful for Tasker
public final static String ACTION_CODE = "action";
public final static String APP_ARG_PREFIX = "app:";
public final static String ICON_ARG_PREFIX = "icn:";
public final static String ARG_INDEX_PREFIX = "arg:";
public static final String PARAM_VAR_NAME_PREFIX = "par";
// Misc
private final static String PERMISSION_RUN_TASKS = TASKER_PACKAGE + ".PERMISSION_RUN_TASKS";
// Intent data
public final static String DEFAULT_ENCRYPTION_KEY = "default";
private final static String ACTION_OPEN_PREFS = TASKER_PACKAGE + ".ACTION_OPEN_PREFS";
public final static String EXTRA_OPEN_PREFS_TAB_NO = "tno";
private final static int MISC_PREFS_TAB_NO = 3; // 0 based
// For particular actions
public final static String ENCRYPTED_AFFIX = "tec";
public final static int MAX_NO_ARGS = 10;
// Bundle keys
// Only useful for Tasker
public final static String ACTION_CODE = "action";
public final static String APP_ARG_PREFIX = "app:";
public final static String ICON_ARG_PREFIX = "icn:";
public final static String ARG_INDEX_PREFIX = "arg:";
public static final String PARAM_VAR_NAME_PREFIX = "par";
public final static String EXTRA_OPEN_PREFS_TAB_NO = "tno";
// Direct-purchase version
private final static String TASKER_DOWNLOAD_URL = "http://tasker.dinglisch.net/download.html";
// Misc
private final static String PERMISSION_RUN_TASKS = TASKER_PACKAGE + ".PERMISSION_RUN_TASKS";
private final static String ACTION_OPEN_PREFS = TASKER_PACKAGE + ".ACTION_OPEN_PREFS";
private final static int MISC_PREFS_TAB_NO = 3; // 0 based
// To query whether Tasker is enabled and external access is enabled
private final static String TASKER_PREFS_URI = "content://" + TASKER_PACKAGE + "/prefs";
private final static int CUPCAKE_SDK_VERSION = 3;
// To query whether Tasker is enabled and external access is enabled
private final static String TASKER_PREFS_URI = "content://" + TASKER_PACKAGE + "/prefs";
// result values for TestSend
private final static int CUPCAKE_SDK_VERSION = 3;
// NotInstalled: Tasker package not found on device
// NoPermission: calling app does not have permission PERMISSION_RUN_TASKS
// NotEnabled: Tasker is not enabled
// AccessBlocked: user prefs disallow external access
// NoReceiver: Tasker has not created a listener for external access (probably a Tasker bug)
// OK: you should be able to send a task to run. Still need to listen for result
// for e.g. task not found
public static enum Status { NotInstalled, NoPermission, NotEnabled, AccessBlocked, NoReceiver, OK };
// result values for TestSend
// -------------------------- PRIVATE VARS ---------------------------- //
// NotInstalled: Tasker package not found on device
// NoPermission: calling app does not have permission PERMISSION_RUN_TASKS
// NotEnabled: Tasker is not enabled
// AccessBlocked: user prefs disallow external access
// NoReceiver: Tasker has not created a listener for external access (probably a Tasker bug)
// OK: you should be able to send a task to run. Still need to listen for result
// for e.g. task not found
private final static String TAG = "TaskerIntent";
private final static String TAG = "TaskerIntent";
// -------------------------- PRIVATE VARS ---------------------------- //
private final static String EXTRA_INTENT_VERSION_NUMBER = "version_number";
private final static String INTENT_VERSION_NUMBER = "1.1";
// Inclusive values
private final static int MIN_PRIORITY = 0;
private final static int MAX_PRIORITY = 10;
// For generating random names
private static final Random rand = new Random();
// Tracking state
private int actionCount = 0;
private int argCount;
private final static String EXTRA_INTENT_VERSION_NUMBER = "version_number";
private final static String INTENT_VERSION_NUMBER = "1.1";
public TaskerIntent() {
super(ACTION_TASK);
setRandomData();
putMetaExtras(getRandomString());
}
// Inclusive values
private final static int MIN_PRIORITY = 0;
private final static int MAX_PRIORITY = 10;
// For generating random names
private static Random rand = new Random();
// -------------------------- PUBLIC METHODS ---------------------------- //
// Tracking state
private int actionCount = 0;
private int argCount;
// -------------------------- PUBLIC METHODS ---------------------------- //
public TaskerIntent(String taskName) {
super(ACTION_TASK);
setRandomData();
putMetaExtras(taskName);
}
public static int getMaxPriority() {
return MAX_PRIORITY;
}
public static boolean validatePriority( int pri ) {
return (
( pri >= MIN_PRIORITY ) ||
( pri <= MAX_PRIORITY )
);
}
// Tasker has different package names for Play Store and non- versions
// for historical reasons
public static String getInstalledTaskerPackage( Context context ) {
String foundPackage = null;
try {
context.getPackageManager().getPackageInfo( TASKER_PACKAGE, 0 );
foundPackage = TASKER_PACKAGE;
}
catch ( PackageManager.NameNotFoundException e ) {
}
public static int getMaxPriority() {
return MAX_PRIORITY;
}
try {
context.getPackageManager().getPackageInfo( TASKER_PACKAGE_MARKET, 0 );
foundPackage = TASKER_PACKAGE_MARKET;
}
catch ( PackageManager.NameNotFoundException e ) {
}
return foundPackage;
}
// test we can send a TaskerIntent to Tasker
// use *before* sending an intent
// still need to test the *result after* sending intent
public static Status testStatus( Context c ) {
// Tasker has different package names for Play Store and non- versions
// for historical reasons
Status result;
if ( ! taskerInstalled( c ) )
result = Status.NotInstalled;
else if ( ! havePermission( c ) )
result = Status.NoPermission;
else if ( ! TaskerIntent.prefSet( c, PROVIDER_COL_NAME_ENABLED ) )
result = Status.NotEnabled;
else if ( ! TaskerIntent.prefSet( c, PROVIDER_COL_NAME_EXTERNAL_ACCESS ) )
result = Status.AccessBlocked;
else if ( ! new TaskerIntent( "" ).receiverExists( c ) )
result = Status.NoReceiver;
else
result = Status.OK;
public static boolean validatePriority(int pri) {
return (
(pri >= MIN_PRIORITY) ||
(pri <= MAX_PRIORITY)
);
}
return result;
}
// test we can send a TaskerIntent to Tasker
// use *before* sending an intent
// still need to test the *result after* sending intent
// Check if Tasker installed
public static String getInstalledTaskerPackage(Context context) {
public static boolean taskerInstalled( Context context ) {
return ( getInstalledTaskerPackage( context ) != null );
}
String foundPackage = null;
// Use with startActivity to retrieve Tasker from Android market
public static Intent getTaskerInstallIntent( boolean marketFlag ) {
return new Intent(
Intent.ACTION_VIEW,
Uri.parse(
marketFlag ?
( ( SDKVersion() == CUPCAKE_SDK_VERSION ) ? TASKER_MARKET_URL_CUPCAKE : TASKER_MARKET_URL ) :
TASKER_DOWNLOAD_URL
)
);
}
try {
context.getPackageManager().getPackageInfo(TASKER_PACKAGE, 0);
foundPackage = TASKER_PACKAGE;
} catch (PackageManager.NameNotFoundException e) {
}
public static int SDKVersion() {
try {
Field f = android.os.Build.VERSION.class.getField( "SDK_INT" );
return f.getInt( null );
}
catch ( Exception e ) {
return CUPCAKE_SDK_VERSION;
}
}
public static IntentFilter getCompletionFilter( String taskName ) {
try {
context.getPackageManager().getPackageInfo(TASKER_PACKAGE_MARKET, 0);
foundPackage = TASKER_PACKAGE_MARKET;
} catch (PackageManager.NameNotFoundException e) {
}
IntentFilter filter = new IntentFilter( TaskerIntent.ACTION_TASK_COMPLETE );
return foundPackage;
}
filter.addDataScheme( TASK_NAME_DATA_SCHEME );
filter.addDataPath( taskName, PatternMatcher.PATTERN_LITERAL );
return filter;
}
// Check if Tasker installed
public static Intent getTaskSelectIntent() {
return new Intent( ACTION_TASK_SELECT ).
setFlags(
Intent.FLAG_ACTIVITY_NO_USER_ACTION |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
Intent.FLAG_ACTIVITY_NO_HISTORY
);
}
// public access deprecated, use TaskerIntent.testSend() instead
public static boolean havePermission( Context c ) {
return c.checkPermission( PERMISSION_RUN_TASKS, Process.myPid(), Process.myUid() ) ==
PackageManager.PERMISSION_GRANTED;
}
public static Status testStatus(Context c) {
// Get an intent that will bring up the Tasker prefs screen with the External Access control(s)
// Probably you want to use startActivity or startActivityForResult with it
public static Intent getExternalAccessPrefsIntent() {
return new Intent( ACTION_OPEN_PREFS ).putExtra( EXTRA_OPEN_PREFS_TAB_NO, MISC_PREFS_TAB_NO );
}
Status result;
// ------------------------------------- INSTANCE METHODS ----------------------------- //
public TaskerIntent() {
super( ACTION_TASK );
setRandomData();
putMetaExtras( getRandomString() );
}
public TaskerIntent( String taskName ) {
super( ACTION_TASK );
setRandomData();
putMetaExtras( taskName );
}
if (!taskerInstalled(c))
result = Status.NotInstalled;
else if (!havePermission(c))
result = Status.NoPermission;
else if (!TaskerIntent.prefSet(c, PROVIDER_COL_NAME_ENABLED))
result = Status.NotEnabled;
else if (!TaskerIntent.prefSet(c, PROVIDER_COL_NAME_EXTERNAL_ACCESS))
result = Status.AccessBlocked;
else if (!new TaskerIntent("").receiverExists(c))
result = Status.NoReceiver;
else
result = Status.OK;
public TaskerIntent setTaskPriority( int priority ) {
return result;
}
if ( validatePriority( priority ) )
putExtra( EXTRA_TASK_PRIORITY, priority );
else
Log.e( TAG, "priority out of range: " + MIN_PRIORITY + ":" + MAX_PRIORITY );
return this;
}
// Sets subsequently %par1, %par2 etc
public TaskerIntent addParameter( String value ) {
int index = 1;
if ( getExtras().containsKey( EXTRA_VAR_NAMES_LIST ) )
index = getExtras().getStringArrayList( EXTRA_VAR_NAMES_LIST ).size() + 1;
Log.d(TAG, "index: " + index );
addLocalVariable( "%" + PARAM_VAR_NAME_PREFIX + index, value );
return this;
}
public static boolean taskerInstalled(Context context) {
return (getInstalledTaskerPackage(context) != null);
}
// Arbitrary specification of (local) variable names and values
public TaskerIntent addLocalVariable( String name, String value ) {
ArrayList<String> names, values;
if ( hasExtra( EXTRA_VAR_NAMES_LIST ) ) {
names = getStringArrayListExtra( EXTRA_VAR_NAMES_LIST );
values = getStringArrayListExtra( EXTRA_VAR_VALUES_LIST );
}
else {
names = new ArrayList<String>();
values = new ArrayList<String>();
// Use with startActivity to retrieve Tasker from Android market
public static Intent getTaskerInstallIntent(boolean marketFlag) {
putStringArrayListExtra( EXTRA_VAR_NAMES_LIST, names );
putStringArrayListExtra( EXTRA_VAR_VALUES_LIST, values );
}
return new Intent(
Intent.ACTION_VIEW,
Uri.parse(
marketFlag ?
((SDKVersion() == CUPCAKE_SDK_VERSION) ? TASKER_MARKET_URL_CUPCAKE : TASKER_MARKET_URL) :
TASKER_DOWNLOAD_URL
)
);
}
names.add( name );
values.add( value );
public static int SDKVersion() {
try {
Field f = android.os.Build.VERSION.class.getField("SDK_INT");
return f.getInt(null);
} catch (Exception e) {
return CUPCAKE_SDK_VERSION;
}
}
return this;
}
public static IntentFilter getCompletionFilter(String taskName) {
public TaskerIntent addAction( int code ) {
actionCount++;
argCount = 1;
Bundle actionBundle = new Bundle();
actionBundle.putInt( ACTION_CODE, code );
IntentFilter filter = new IntentFilter(TaskerIntent.ACTION_TASK_COMPLETE);
// Add action bundle to intent
putExtra( EXTRA_ACTION_INDEX_PREFIX + Integer.toString( actionCount ), actionBundle );
filter.addDataScheme(TASK_NAME_DATA_SCHEME);
filter.addDataPath(taskName, PatternMatcher.PATTERN_LITERAL);
return this;
}
// string arg
public TaskerIntent addArg( String arg ) {
return filter;
}
Bundle b = getActionBundle();
// public access deprecated, use TaskerIntent.testSend() instead
if ( b != null )
b.putString( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg );
return this;
}
// int arg
public TaskerIntent addArg( int arg ) {
Bundle b = getActionBundle();
public static Intent getTaskSelectIntent() {
return new Intent(ACTION_TASK_SELECT).
setFlags(
Intent.FLAG_ACTIVITY_NO_USER_ACTION |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
Intent.FLAG_ACTIVITY_NO_HISTORY
);
}
if ( b != null )
b.putInt( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg );
return this;
}
// boolean arg
public TaskerIntent addArg( boolean arg ) {
Bundle b = getActionBundle();
// Get an intent that will bring up the Tasker prefs screen with the External Access control(s)
// Probably you want to use startActivity or startActivityForResult with it
if ( b != null )
b.putBoolean( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg );
return this;
}
public static boolean havePermission(Context c) {
return c.checkPermission(PERMISSION_RUN_TASKS, Process.myPid(), Process.myUid()) ==
PackageManager.PERMISSION_GRANTED;
}
// Application arg
public TaskerIntent addArg( String pkg, String cls ) {
Bundle b = getActionBundle();
// ------------------------------------- INSTANCE METHODS ----------------------------- //
if ( b != null ) {
StringBuilder builder = new StringBuilder();
builder.append( APP_ARG_PREFIX ).
append( pkg ). append( "," ). append( cls );
b.putString( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), b.toString() );
}
return this;
}
public static Intent getExternalAccessPrefsIntent() {
return new Intent(ACTION_OPEN_PREFS).putExtra(EXTRA_OPEN_PREFS_TAB_NO, MISC_PREFS_TAB_NO);
}
public IntentFilter getCompletionFilter() {
return getCompletionFilter( getTaskName() );
}
private static boolean prefSet(Context context, String col) {
public String getTaskName() {
return getStringExtra( EXTRA_TASK_NAME );
}
String[] proj = new String[]{col};
public boolean receiverExists( Context context ) {
List<ResolveInfo> recs = context.getPackageManager().queryBroadcastReceivers( this, 0 );
return (
( recs != null ) &&
( recs.size() > 0 )
);
}
Cursor c = context.getContentResolver().query(Uri.parse(TASKER_PREFS_URI), proj, null, null, null);
// -------------------- PRIVATE METHODS -------------------- //
private String getRandomString() {
return Long.toString( rand.nextLong() );
}
boolean acceptingFlag = false;
// so that if multiple TaskerIntents are used in PendingIntents there's virtually no
// clash chance
private void setRandomData() {
setData( Uri.parse( TASK_ID_SCHEME + ":" + getRandomString() ) );
}
private Bundle getActionBundle() {
if (c == null)
Log.w(TAG, "no cursor for " + TASKER_PREFS_URI);
else {
c.moveToFirst();
Bundle toReturn = null;
if ( argCount > MAX_NO_ARGS )
Log.e( TAG, "maximum number of arguments exceeded (" + MAX_NO_ARGS + ")" );
else {
String key = EXTRA_ACTION_INDEX_PREFIX + Integer.toString( actionCount );
if (Boolean.TRUE.toString().equals(c.getString(0)))
acceptingFlag = true;
if ( this.hasExtra( key ) )
toReturn = getBundleExtra( key );
else
Log.e( TAG, "no actions added yet" );
}
return toReturn;
}
private void putMetaExtras( String taskName ) {
putExtra( EXTRA_INTENT_VERSION_NUMBER, INTENT_VERSION_NUMBER );
putExtra( EXTRA_TASK_NAME, taskName );
}
c.close();
}
// for testing that Tasker is enabled and external access is allowed
private static boolean prefSet( Context context, String col ) {
String [] proj = new String [] { col };
return acceptingFlag;
}
Cursor c = context.getContentResolver().query( Uri.parse( TASKER_PREFS_URI ), proj, null, null, null );
public TaskerIntent setTaskPriority(int priority) {
boolean acceptingFlag = false;
if ( c == null )
Log.w( TAG, "no cursor for " + TASKER_PREFS_URI );
else {
c.moveToFirst();
if ( Boolean.TRUE.toString().equals( c.getString( 0 ) ) )
acceptingFlag = true;
if (validatePriority(priority))
putExtra(EXTRA_TASK_PRIORITY, priority);
else
Log.e(TAG, "priority out of range: " + MIN_PRIORITY + ":" + MAX_PRIORITY);
c.close();
}
return acceptingFlag;
}
return this;
}
// Sets subsequently %par1, %par2 etc
public TaskerIntent addParameter(String value) {
int index = 1;
if (getExtras().containsKey(EXTRA_VAR_NAMES_LIST))
index = getExtras().getStringArrayList(EXTRA_VAR_NAMES_LIST).size() + 1;
Log.d(TAG, "index: " + index);
addLocalVariable("%" + PARAM_VAR_NAME_PREFIX + index, value);
return this;
}
// Arbitrary specification of (local) variable names and values
public TaskerIntent addLocalVariable(String name, String value) {
ArrayList<String> names, values;
if (hasExtra(EXTRA_VAR_NAMES_LIST)) {
names = getStringArrayListExtra(EXTRA_VAR_NAMES_LIST);
values = getStringArrayListExtra(EXTRA_VAR_VALUES_LIST);
} else {
names = new ArrayList<String>();
values = new ArrayList<String>();
putStringArrayListExtra(EXTRA_VAR_NAMES_LIST, names);
putStringArrayListExtra(EXTRA_VAR_VALUES_LIST, values);
}
names.add(name);
values.add(value);
return this;
}
public TaskerIntent addAction(int code) {
actionCount++;
argCount = 1;
Bundle actionBundle = new Bundle();
actionBundle.putInt(ACTION_CODE, code);
// Add action bundle to intent
putExtra(EXTRA_ACTION_INDEX_PREFIX + actionCount, actionBundle);
return this;
}
// string arg
public TaskerIntent addArg(String arg) {
Bundle b = getActionBundle();
if (b != null)
b.putString(ARG_INDEX_PREFIX + argCount++, arg);
return this;
}
// int arg
public TaskerIntent addArg(int arg) {
Bundle b = getActionBundle();
if (b != null)
b.putInt(ARG_INDEX_PREFIX + argCount++, arg);
return this;
}
// boolean arg
public TaskerIntent addArg(boolean arg) {
Bundle b = getActionBundle();
if (b != null)
b.putBoolean(ARG_INDEX_PREFIX + argCount++, arg);
return this;
}
// Application arg
public TaskerIntent addArg(String pkg, String cls) {
Bundle b = getActionBundle();
if (b != null) {
StringBuilder builder = new StringBuilder();
builder.append(APP_ARG_PREFIX).
append(pkg).append(",").append(cls);
b.putString(ARG_INDEX_PREFIX + argCount++, b.toString());
}
return this;
}
public IntentFilter getCompletionFilter() {
return getCompletionFilter(getTaskName());
}
public String getTaskName() {
return getStringExtra(EXTRA_TASK_NAME);
}
public boolean receiverExists(Context context) {
List<ResolveInfo> recs = context.getPackageManager().queryBroadcastReceivers(this, 0);
return (
(recs != null) &&
(recs.size() > 0)
);
}
// -------------------- PRIVATE METHODS -------------------- //
private String getRandomString() {
return Long.toString(rand.nextLong());
}
// so that if multiple TaskerIntents are used in PendingIntents there's virtually no
// clash chance
private void setRandomData() {
setData(Uri.parse(TASK_ID_SCHEME + ":" + getRandomString()));
}
private Bundle getActionBundle() {
Bundle toReturn = null;
if (argCount > MAX_NO_ARGS)
Log.e(TAG, "maximum number of arguments exceeded (" + MAX_NO_ARGS + ")");
else {
String key = EXTRA_ACTION_INDEX_PREFIX + actionCount;
if (this.hasExtra(key))
toReturn = getBundleExtra(key);
else
Log.e(TAG, "no actions added yet");
}
return toReturn;
}
private void putMetaExtras(String taskName) {
putExtra(EXTRA_INTENT_VERSION_NUMBER, INTENT_VERSION_NUMBER);
putExtra(EXTRA_TASK_NAME, taskName);
}
// for testing that Tasker is enabled and external access is allowed
public enum Status {NotInstalled, NoPermission, NotEnabled, AccessBlocked, NoReceiver, OK}
}

View file

@ -26,90 +26,88 @@ import android.graphics.drawable.Drawable;
* This drawable that draws a simple white and gray chessboard pattern.
* It's pattern you will often see as a background behind a
* partly transparent image in many applications.
*
* @author Daniel Nilsson
*/
public class AlphaPatternDrawable extends Drawable {
private int mRectangleSize = 10;
// private Paint mPaint = new Paint();
private final Paint mPaintWhite = new Paint();
private final Paint mPaintGray = new Paint();
private int mRectangleSize = 10;
private int numRectanglesHorizontal;
private int numRectanglesVertical;
// private Paint mPaint = new Paint();
private Paint mPaintWhite = new Paint();
private Paint mPaintGray = new Paint();
private int numRectanglesHorizontal;
private int numRectanglesVertical;
/**
* Bitmap in which the pattern will be cahched.
*/
/**
* Bitmap in which the pattern will be cahched.
*/
// private Bitmap mBitmap;
public AlphaPatternDrawable(int rectangleSize) {
mRectangleSize = rectangleSize;
mPaintWhite.setColor(0xffffffff);
mPaintGray.setColor(0xffcbcbcb);
}
public AlphaPatternDrawable(int rectangleSize) {
mRectangleSize = rectangleSize;
mPaintWhite.setColor(0xffffffff);
mPaintGray.setColor(0xffcbcbcb);
}
@Override
public void draw(Canvas canvas) {
@Override
public void draw(Canvas canvas) {
// canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
Rect bounds = getBounds();
canvas.clipRect(bounds);
canvas.translate(bounds.left, bounds.top);
Rect r = new Rect();
boolean verticalStartWhite = true;
for (int i = 0; i <= numRectanglesVertical; i++) {
boolean isWhite = verticalStartWhite;
for (int j = 0; j <= numRectanglesHorizontal; j++) {
Rect bounds = getBounds();
r.top = i * mRectangleSize;
r.left = j * mRectangleSize;
r.bottom = r.top + mRectangleSize;
r.right = r.left + mRectangleSize;
canvas.clipRect(bounds);
canvas.translate(bounds.left, bounds.top);
canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
Rect r = new Rect();
boolean verticalStartWhite = true;
for (int i = 0; i <= numRectanglesVertical; i++) {
isWhite = !isWhite;
}
boolean isWhite = verticalStartWhite;
for (int j = 0; j <= numRectanglesHorizontal; j++) {
verticalStartWhite = !verticalStartWhite;
r.top = i * mRectangleSize;
r.left = j * mRectangleSize;
r.bottom = r.top + mRectangleSize;
r.right = r.left + mRectangleSize;
}
canvas.translate(-bounds.left, -bounds.top);
}
canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
@Override
public int getOpacity() {
return 0;
}
isWhite = !isWhite;
}
@Override
public void setAlpha(int alpha) {
verticalStartWhite = !verticalStartWhite;
}
canvas.translate(-bounds.left, -bounds.top);
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
// throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
}
}
@Override
public void setColorFilter(ColorFilter cf) {
@Override
public void setColorFilter(ColorFilter cf) {
// throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
}
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
int height = bounds.height();
int width = bounds.width();
int height = bounds.height();
int width = bounds.width();
numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
// generatePatternBitmap();
}
}
// /**
// * This will generate a bitmap with the pattern

View file

@ -28,129 +28,124 @@ import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import net.pierrox.lightning_launcher.R;
public class ColorPickerDialog
extends
Dialog
implements
ColorPickerView.OnColorChangedListener,
View.OnClickListener, DialogInterface.OnCancelListener {
public class ColorPickerDialog
extends
Dialog
implements
ColorPickerView.OnColorChangedListener,
View.OnClickListener, DialogInterface.OnCancelListener {
private ColorPickerView mColorPicker;
private ColorPickerView mColorPicker;
private ColorPickerPanelView mOldColor;
private ColorPickerPanelView mNewColor;
private EditText mHexEditor;
private ColorPickerPanelView mOldColor;
private ColorPickerPanelView mNewColor;
private EditText mHexEditor;
private OnColorChangedListener mListener;
private OnColorChangedListener mListener;
public ColorPickerDialog(Context context, int initialColor) {
super(context);
init(initialColor);
}
@Override
public void onCancel(DialogInterface dialogInterface) {
if(mListener != null) mListener.onColorDialogCanceled();
if (mListener != null) mListener.onColorDialogCanceled();
}
public interface OnColorChangedListener {
public void onColorChanged(int color);
public void onColorDialogSelected(int color);
public void onColorDialogCanceled();
}
public ColorPickerDialog(Context context, int initialColor) {
super(context);
private void init(int color) {
// To fight color banding.
getWindow().setFormat(PixelFormat.RGBA_8888);
init(initialColor);
}
setUp(color);
private void init(int color) {
// To fight color banding.
getWindow().setFormat(PixelFormat.RGBA_8888);
}
setUp(color);
private void setUp(int color) {
}
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
private void setUp(int color) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dialog_color_picker, null);
View layout = inflater.inflate(R.layout.dialog_color_picker, null);
setContentView(layout);
setContentView(layout);
setTitle(R.string.dialog_color_picker);
mColorPicker = (ColorPickerView) layout.findViewById(R.id.color_picker_view);
mOldColor = (ColorPickerPanelView) layout.findViewById(R.id.old_color_panel);
mNewColor = (ColorPickerPanelView) layout.findViewById(R.id.new_color_panel);
mHexEditor = (EditText) layout.findViewById(R.id.hex_editor);
mHexEditor.clearFocus();
InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if ( dest.length() - (dend-dstart) + (end -start) > 8) {
return "";
}
setTitle(R.string.dialog_color_picker);
boolean ok=true;
for (int i = start; i < end; i++) {
char c = source.charAt(i);
if ( !((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F')) ) {
ok=false;
break;
}
}
return ok ? null : "";
}
};
mHexEditor.setFilters(new InputFilter[] { filter });
mHexEditor.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// pass
}
mColorPicker = layout.findViewById(R.id.color_picker_view);
mOldColor = layout.findViewById(R.id.old_color_panel);
mNewColor = layout.findViewById(R.id.new_color_panel);
mHexEditor = layout.findViewById(R.id.hex_editor);
mHexEditor.clearFocus();
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// pass
}
InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (dest.length() - (dend - dstart) + (end - start) > 8) {
return "";
}
boolean ok = true;
for (int i = start; i < end; i++) {
char c = source.charAt(i);
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
ok = false;
break;
}
}
return ok ? null : "";
}
};
mHexEditor.setFilters(new InputFilter[]{filter});
mHexEditor.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// pass
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// pass
}
@Override
public void afterTextChanged(Editable s) {
try {
int color = Color.parseColor("#" + fillHex(s.toString()));
if (color != mColorPicker.getColor()) {
mColorPicker.setColor(color, false);
mNewColor.setColor(color);
}
} catch (Exception e) {
// pass
e.printStackTrace();
}
}
});
@Override
public void afterTextChanged(Editable s) {
try {
int color = Color.parseColor("#" + fillHex(s.toString()));
if (color != mColorPicker.getColor()) {
mColorPicker.setColor(color, false);
mNewColor.setColor(color);
}
} catch(Exception e) {
// pass
e.printStackTrace();
}
}
});
// ((LinearLayout) mOldColor.getParent()).setPadding(
// Math.round(mColorPicker.getDrawingOffset()),
// 0,
// Math.round(mColorPicker.getDrawingOffset()),
// Math.round(mColorPicker.getDrawingOffset()),
// 0,
// Math.round(mColorPicker.getDrawingOffset()),
// 0
// );
mOldColor.setOnClickListener(this);
mNewColor.setOnClickListener(this);
mColorPicker.setOnColorChangedListener(this);
mOldColor.setColor(color);
mColorPicker.setColor(color, true);
// );
mOldColor.setOnClickListener(this);
mNewColor.setOnClickListener(this);
mColorPicker.setOnColorChangedListener(this);
mOldColor.setColor(color);
mColorPicker.setColor(color, true);
setOnCancelListener(this);
}
}
@Override
public void onColorChanged(int color) {
@Override
public void onColorChanged(int color) {
mNewColor.setColor(color);
mNewColor.setColor(color);
/*
if (mListener != null) {
@ -158,37 +153,38 @@ public class ColorPickerDialog
}
*/
String hex=Integer.toHexString(color);
mHexEditor.setText(fillHex(hex));
}
private String fillHex(String hex) {
while(hex.length()<8) {
hex='0'+hex;
}
return hex;
}
String hex = Integer.toHexString(color);
public void setAlphaSliderVisible(boolean visible) {
mColorPicker.setAlphaSliderVisible(visible);
}
/**
* Set a OnColorChangedListener to get notified when the color
* selected by the user has changed.
* @param listener
*/
public void setOnColorChangedListener(OnColorChangedListener listener){
mListener = listener;
}
mHexEditor.setText(fillHex(hex));
}
public int getColor() {
return mColorPicker.getColor();
}
private String fillHex(String hex) {
while (hex.length() < 8) {
hex = '0' + hex;
}
return hex;
}
@Override
public void onClick(View v) {
public void setAlphaSliderVisible(boolean visible) {
mColorPicker.setAlphaSliderVisible(visible);
}
/**
* Set a OnColorChangedListener to get notified when the color
* selected by the user has changed.
*
* @param listener
*/
public void setOnColorChangedListener(OnColorChangedListener listener) {
mListener = listener;
}
public int getColor() {
return mColorPicker.getColor();
}
@Override
public void onClick(View v) {
if (mListener != null) {
int color = mNewColor.getColor();
int id = v.getId();
@ -200,8 +196,16 @@ public class ColorPickerDialog
mListener.onColorDialogCanceled();
}
}
dismiss();
}
dismiss();
}
public interface OnColorChangedListener {
void onColorChanged(int color);
void onColorDialogSelected(int color);
void onColorDialogCanceled();
}
//
// @Override
// public Bundle onSaveInstanceState() {

View file

@ -12,6 +12,7 @@ import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.view.ViewGroup;
import net.pierrox.lightning_launcher.activities.ResourcesWrapperHelper;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.SystemConfig;
@ -26,6 +27,7 @@ import net.pierrox.lightning_launcher.script.api.Property;
import net.pierrox.lightning_launcher.views.MyAppWidgetHostView;
import net.pierrox.lightning_launcher.views.NativeImage;
import net.pierrox.lightning_launcher.views.SharedAsyncGraphicsDrawable;
import org.json.JSONObject;
import java.io.File;
@ -34,86 +36,91 @@ import java.util.HashMap;
import java.util.List;
public abstract class LLApp extends Application {
public interface SystemConfigListener {
void onSystemConfigChanged(SystemConfig newSystemConfig);
}
public static final String LL_PKG_NAME="net.pierrox.lightning_launcher";
public static final String LLX_PKG_NAME="net.pierrox.lightning_launcher_extreme";
public static final String LKP_PKG_NAME="net.pierrox.lightning_locker_p";
public static final String INTENT_ITEM_ACTION=LL_PKG_NAME+".ITEM_ACTION";
public static final String LL_PKG_NAME = "net.pierrox.lightning_launcher";
public static final String LLX_PKG_NAME = "net.pierrox.lightning_launcher_extreme";
public static final String LKP_PKG_NAME = "net.pierrox.lightning_locker_p";
public static final String INTENT_ITEM_ACTION = LL_PKG_NAME + ".ITEM_ACTION";
private static final int SYSTEM_CONFIG_FILE_VERSION = 1;
private static LLApp sThis;
private final HashMap<String, LightningEngine> mLightningEngines = new HashMap<>();
private final ArrayList<Screen> mScreens = new ArrayList<>();
protected LightningEngine mAppEngine;
private HashMap<String, LightningEngine> mLightningEngines = new HashMap<>();
private MyAppWidgetHost mAppWidgetHost;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Screen screen = getActiveScreen();
if (screen != null) {
screen.runAction(mAppEngine, "SCREEN_OFF", mAppEngine.getGlobalConfig().screenOff);
}
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Screen screen = getActiveScreen();
if (screen != null) {
screen.runAction(mAppEngine, "SCREEN_ON", mAppEngine.getGlobalConfig().screenOn);
}
}
}
};
protected SystemConfig mSystemConfig;
private ArrayList<SystemConfigListener> mSystemConfigListeners;
protected Screen mBackgroundScreen;
private MyAppWidgetHost mAppWidgetHost;
private ArrayList<SystemConfigListener> mSystemConfigListeners;
private ResourcesWrapperHelper mResourcesWrapperHelper;
private String mLanguage;
private String mLanguage;
private int mActiveDashboardPage;
private Typeface mIconsTypeface;
private int mWidgetHostStartListeningCount;
private ArrayList<Screen> mScreens = new ArrayList<>();
protected Screen mBackgroundScreen;
public static LLApp get() {
return sThis;
}
@Override
public void onCreate() {
super.onCreate();
@Override
public void onCreate() {
super.onCreate();
sThis = this;
NativeImage.init(this);
NativeImage.init(this);
Utils.deleteDirectory(FileUtils.getCachedDrawablesDir(this), false);
mAppWidgetHost=new MyAppWidgetHost(this, 1968);
mAppWidgetHost = new MyAppWidgetHost(this, 1968);
try {
mAppWidgetHost.startListening();
} catch (Throwable e) {
// pass
}
mSystemConfigListeners=new ArrayList<>(10);
mSystemConfigListeners = new ArrayList<>(10);
loadSystemConfig();
migrate();
Utils.retrieveStandardIcon(this);
Utils.retrieveStandardIcon(this);
SharedAsyncGraphicsDrawable.setPoolSize((long) (mSystemConfig.imagePoolSize * Runtime.getRuntime().maxMemory()));
// Utils.setTheme(this, Utils.APP_THEME);
if(mSystemConfig.language != null) {
if (mSystemConfig.language != null) {
mLanguage = mSystemConfig.language;
} else {
List<ResolveInfo> r=getPackageManager().queryIntentActivities(new Intent("net.pierrox.lightning_launcher.lp.ENUMERATE"), 0);
} else {
List<ResolveInfo> r = getPackageManager().queryIntentActivities(new Intent("net.pierrox.lightning_launcher.lp.ENUMERATE"), 0);
mLanguage = null;
for(ResolveInfo ri : r) {
for (ResolveInfo ri : r) {
String p = ri.activityInfo.packageName;
if(!p.equals(LL_PKG_NAME) && !p.equals(LLX_PKG_NAME)) {
if (!p.equals(LL_PKG_NAME) && !p.equals(LLX_PKG_NAME)) {
mLanguage = p;
break;
}
}
}
}
if(getPackageName().equals(mLanguage)) {
if (getPackageName().equals(mLanguage)) {
mLanguage = null;
}
@ -129,17 +136,17 @@ public abstract class LLApp extends Application {
mAppEngine.getOrLoadPage(Page.APP_DRAWER_PAGE);
IntentFilter intent_filter=new IntentFilter();
IntentFilter intent_filter = new IntentFilter();
intent_filter.addAction(Intent.ACTION_SCREEN_OFF);
intent_filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mBroadcastReceiver, intent_filter);
mBackgroundScreen.runAction(mAppEngine, "STARTUP", mAppEngine.getGlobalConfig().startup);
}
@Override
public void onTerminate() {
super.onTerminate();
@Override
public void onTerminate() {
super.onTerminate();
unregisterReceiver(mBroadcastReceiver);
@ -162,10 +169,10 @@ public abstract class LLApp extends Application {
saveSystemConfig();
}
@Override
public Resources getResources() {
return mResourcesWrapperHelper == null ? super.getResources() : mResourcesWrapperHelper.getResources();
}
@Override
public Resources getResources() {
return mResourcesWrapperHelper == null ? super.getResources() : mResourcesWrapperHelper.getResources();
}
public SystemConfig getSystemConfig() {
return mSystemConfig;
@ -179,9 +186,9 @@ public abstract class LLApp extends Application {
public LightningEngine getEngine(File baseDir, boolean doInit) {
String key = baseDir.getAbsolutePath();
LightningEngine engine = mLightningEngines.get(key);
if(engine == null) {
if (engine == null) {
engine = new LightningEngine(this, baseDir);
if(doInit) {
if (doInit) {
engine.init();
}
mLightningEngines.put(key, engine);
@ -190,35 +197,31 @@ public abstract class LLApp extends Application {
return engine;
}
public void notifySystemConfigChanged() {
for(SystemConfigListener l : mSystemConfigListeners) {
l.onSystemConfigChanged(mSystemConfig);
}
}
public void notifySystemConfigChanged() {
for (SystemConfigListener l : mSystemConfigListeners) {
l.onSystemConfigChanged(mSystemConfig);
}
}
public void saveSystemConfig() {
mSystemConfig.version = SYSTEM_CONFIG_FILE_VERSION;
JsonLoader.saveObjectToFile(mSystemConfig, FileUtils.getSystemConfigFile(this));
}
public void registerSystemConfigListener(SystemConfigListener l) {
public void registerSystemConfigListener(SystemConfigListener l) {
mSystemConfigListeners.add(l);
}
public void unregisterSystemConfigListener(SystemConfigListener l) {
}
public void unregisterSystemConfigListener(SystemConfigListener l) {
mSystemConfigListeners.remove(l);
}
public static LLApp get() {
return sThis;
}
public MyAppWidgetHost getAppWidgetHost() {
}
public MyAppWidgetHost getAppWidgetHost() {
return mAppWidgetHost;
}
}
public void appWidgetHostStartListening() {
if(mWidgetHostStartListeningCount == 0) {
if (mWidgetHostStartListeningCount == 0) {
mAppWidgetHost.startListening();
}
mWidgetHostStartListeningCount++;
@ -226,28 +229,28 @@ public abstract class LLApp extends Application {
public void appWidgetHostStopListening() {
mWidgetHostStartListeningCount--;
if(mWidgetHostStartListeningCount == 0) {
if (mWidgetHostStartListeningCount == 0) {
mAppWidgetHost.stopListening();
}
}
public abstract void displayPagerPage(int page, boolean reset_navigation_history);
public int getActiveDashboardPage() {
return mActiveDashboardPage;
}
public void setActiveDashboardPage(int page) {
mActiveDashboardPage = page;
}
public int getActiveDashboardPage() {
return mActiveDashboardPage;
protected void loadSystemConfig() {
mSystemConfig = JsonLoader.readObject(SystemConfig.class, FileUtils.getSystemConfigFile(this));
}
protected void loadSystemConfig() {
mSystemConfig = JsonLoader.readObject(SystemConfig.class, FileUtils.getSystemConfigFile(this));
}
public void onScreenCreated(Screen screen) {
int index;
if(screen.getIdentity() == ScreenIdentity.LIVE_WALLPAPER) {
if (screen.getIdentity() == ScreenIdentity.LIVE_WALLPAPER) {
// never put the live wallpaper at the top of the stack, always the bottom
index = 0;
} else {
@ -262,7 +265,7 @@ public abstract class LLApp extends Application {
public void onScreenResumed(Screen screen) {
// never bring the LWP to the top of the stack
if(screen.getIdentity() != ScreenIdentity.LIVE_WALLPAPER && mScreens.size() > 1) {
if (screen.getIdentity() != ScreenIdentity.LIVE_WALLPAPER && mScreens.size() > 1) {
mScreens.remove(screen);
mScreens.add(screen);
}
@ -270,7 +273,7 @@ public abstract class LLApp extends Application {
public void onScreenPaused(Screen screen) {
// the LWP is always at the bottom of the stack
if(screen.getIdentity() != ScreenIdentity.LIVE_WALLPAPER) {
if (screen.getIdentity() != ScreenIdentity.LIVE_WALLPAPER) {
int size = mScreens.size();
if (size > 2) {
mScreens.remove(screen);
@ -281,7 +284,7 @@ public abstract class LLApp extends Application {
public Screen getScreen(ScreenIdentity identity) {
for (Screen screen : mScreens) {
if(screen.getIdentity() == identity) {
if (screen.getIdentity() == identity) {
return screen;
}
}
@ -294,11 +297,11 @@ public abstract class LLApp extends Application {
public Screen getActiveScreen() {
int l = mScreens.size();
return l==0 ? null : mScreens.get(l-1);
return l == 0 ? null : mScreens.get(l - 1);
}
public Typeface getIconsTypeface() {
if(mIconsTypeface == null) {
if (mIconsTypeface == null) {
mIconsTypeface = Typeface.createFromAsset(getAssets(), "icons.ttf");
}
return mIconsTypeface;
@ -365,52 +368,69 @@ public abstract class LLApp extends Application {
private void migrate() {
// migrate fields that were previously in the global config object
if(mSystemConfig.version == 0) {
if (mSystemConfig.version == 0) {
File from = FileUtils.getGlobalConfigFile(getFilesDir());
JSONObject json = FileUtils.readJSONObjectFromFile(from);
if(json != null) {
if (json != null) {
mSystemConfig.autoEdit = json.optBoolean("autoEdit", false);
mSystemConfig.alwaysShowStopPoints = json.optBoolean("alwaysShowStopPoints", false);
mSystemConfig.keepInMemory = json.optBoolean("keepInMemory", true);
mSystemConfig.language = json.optString("language", null);
mSystemConfig.expertMode = json.optBoolean("expertMode", false);
mSystemConfig.hotwords = json.optBoolean("hotwords", false);
if(json.has("appStyle")) mSystemConfig.appStyle = SystemConfig.AppStyle.valueOf(json.optString("appStyle"));
if (json.has("appStyle"))
mSystemConfig.appStyle = SystemConfig.AppStyle.valueOf(json.optString("appStyle"));
mSystemConfig.hints = json.optInt("hints", 0);
if(json.optBoolean("showHelpHint", true)) mSystemConfig.hints |= SystemConfig.HINT_CUSTOMIZE_HELP;
if(json.optBoolean("showRateHint", true)) mSystemConfig.hints |= SystemConfig.HINT_RATE;
if(json.optBoolean("myDrawerHint", true)) mSystemConfig.hints |= SystemConfig.HINT_MY_DRAWER;
if (json.optBoolean("showHelpHint", true))
mSystemConfig.hints |= SystemConfig.HINT_CUSTOMIZE_HELP;
if (json.optBoolean("showRateHint", true))
mSystemConfig.hints |= SystemConfig.HINT_RATE;
if (json.optBoolean("myDrawerHint", true))
mSystemConfig.hints |= SystemConfig.HINT_MY_DRAWER;
mSystemConfig.imagePoolSize = (float) json.optDouble("imagePoolSize", 0);
mSystemConfig.switches = json.optInt("switches", SystemConfig.SWITCH_SNAP|SystemConfig.SWITCH_EDIT_BARS|SystemConfig.SWITCH_CONTENT_ZOOMED|SystemConfig.SWITCH_HONOUR_PINNED_ITEMS);
mSystemConfig.switches = json.optInt("switches", SystemConfig.SWITCH_SNAP | SystemConfig.SWITCH_EDIT_BARS | SystemConfig.SWITCH_CONTENT_ZOOMED | SystemConfig.SWITCH_HONOUR_PINNED_ITEMS);
mSystemConfig.editBoxMode = json.optInt("editBoxMode", SystemConfig.EDIT_BOX_NONE);
mSystemConfig.editBoxPropHeight = json.optInt("editBoxPropHeight", 0);
}
}
// update the version number now
if(mSystemConfig.version < SYSTEM_CONFIG_FILE_VERSION) {
if (mSystemConfig.version < SYSTEM_CONFIG_FILE_VERSION) {
saveSystemConfig();
}
}
private BroadcastReceiver mBroadcastReceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Screen screen = getActiveScreen();
if(screen != null) {
screen.runAction(mAppEngine, "SCREEN_OFF", mAppEngine.getGlobalConfig().screenOff);
}
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Screen screen = getActiveScreen();
if(screen != null) {
screen.runAction(mAppEngine, "SCREEN_ON", mAppEngine.getGlobalConfig().screenOn);
}
}
public interface SystemConfigListener {
void onSystemConfigChanged(SystemConfig newSystemConfig);
}
public static final class MyAppWidgetHost extends AppWidgetHost {
HashMap<Integer, AppWidgetHostView> mViews = new HashMap<>();
public MyAppWidgetHost(Context context, int hostId) {
super(context, hostId);
}
};
public AppWidgetHostView getWidgetView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
AppWidgetHostView v = mViews.get(appWidgetId);
if (v == null) {
v = createView(context, appWidgetId, appWidget);
mViews.put(appWidgetId, v);
} else {
ViewGroup parent = (ViewGroup) v.getParent();
parent.removeView(v);
}
return v;
}
@Override
protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
return new MyAppWidgetHostView(context);
}
}
private class BackgroundScreen extends Screen {
@ -429,31 +449,4 @@ public abstract class LLApp extends Application {
}
}
public static final class MyAppWidgetHost extends AppWidgetHost {
HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
public MyAppWidgetHost(Context context, int hostId) {
super(context, hostId);
}
public AppWidgetHostView getWidgetView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
AppWidgetHostView v = mViews.get(appWidgetId);
if(v == null) {
v = createView(context, appWidgetId, appWidget);
mViews.put(appWidgetId, v);
} else {
ViewGroup parent = (ViewGroup) v.getParent();
parent.removeView(v);
}
return v;
}
@Override
protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
return new MyAppWidgetHostView(context);
}
}
}

View file

@ -8,24 +8,24 @@ import net.pierrox.lightning_launcher.util.ResourcesWrapper;
public class ResourcesWrapperHelper {
private Resources mBaseResources;
private final Resources mBaseResources;
private ResourcesWrapper mResourcesWrapper;
public ResourcesWrapperHelper(Context context, Resources base_resources) {
mBaseResources = base_resources;
String language = LLApp.get().getLanguage();
if (language != null) {
mResourcesWrapper = new ResourcesWrapper(mBaseResources);
mResourcesWrapper.setTranslationPackageName(context, language);
}
}
public final Resources getResources() {
if(mResourcesWrapper != null) {
if (mResourcesWrapper != null) {
return mResourcesWrapper;
} else {
return mBaseResources;
}
}
public ResourcesWrapperHelper(Context context, Resources base_resources) {
mBaseResources = base_resources;
String language = LLApp.get().getLanguage();
if(language != null) {
mResourcesWrapper = new ResourcesWrapper(mBaseResources);
mResourcesWrapper.setTranslationPackageName(context, language);
}
}
}

View file

@ -1,7 +1,9 @@
package net.pierrox.lightning_launcher.configuration;
public interface FolderConfigStylable {
public FolderConfig getFolderConfig();
public void setFolderConfig(FolderConfig fc);
public FolderConfig modifyFolderConfig();
FolderConfig getFolderConfig();
void setFolderConfig(FolderConfig fc);
FolderConfig modifyFolderConfig();
}

View file

@ -6,14 +6,138 @@ import net.pierrox.lightning_launcher.data.Page;
public class GlobalConfig extends JsonLoader {
public enum PageAnimation {
NONE,
FADE,
SLIDE_H,
SLIDE_V
}
public static final int CATEGORY = -1;
public static final int UNSET = 0;
public static final int NOTHING = 1;
public static final int APP_DRAWER = 2;
public static final int ZOOM_FULL_SCALE = 3;
public static final int ZOOM_TO_ORIGIN = 4;
public static final int SWITCH_FULL_SCALE_OR_ORIGIN = 5;
public static final int SHOW_HIDE_STATUS_BAR = 6;
public static final int LAUNCHER_MENU = 7;
public static final int EDIT_LAYOUT = 8;
public static final int CUSTOMIZE_LAUNCHER = 9;
public static final int CUSTOMIZE_DESKTOP = 10;
public static final int CUSTOMIZE_ITEM = 11;
public static final int ITEM_MENU = 12;
public static final int LAUNCH_ITEM = 13;
public static final int SEARCH = 14;
public static final int SHOW_HIDE_APP_MENU = 15;
public static final int SHOW_HIDE_APP_MENU_STATUS_BAR = 16;
public static final int SHOW_NOTIFICATIONS = 17;
public static final int PREVIOUS_DESKTOP = 18;
public static final int NEXT_DESKTOP = 19;
public static final int LAUNCH_APP = 20;
public static final int MOVE_ITEM = 21;
public static final int ADD_ITEM = 22;
public static final int LAUNCH_SHORTCUT = 23;
public static final int SELECT_WALLPAPER = 24;
public static final int GO_HOME = 25;
public static final int GO_HOME_ZOOM_TO_ORIGIN = 26;
public static final int SELECT_DESKTOP_TO_GO_TO = 27;
public static final int RESTART = 28;
public static final int CLOSE_TOPMOST_FOLDER = 29;
public static final int CLOSE_ALL_FOLDERS = 30;
public static final int SEARCH_APP = 31;
public static final int OPEN_FOLDER = 32;
public static final int GO_DESKTOP_POSITION = 33;
public static final int UNLOCK_SCREEN = 34;
public static final int RUN_SCRIPT = 35;
public static final int BACK = 36;
public static final int CUSTOM_MENU = 37;
public static final int USER_MENU = 38;
public static final int WALLPAPER_TAP = 39;
public static final int WALLPAPER_SECONDARY_TAP = 40;
public static final int SET_VARIABLE = 41;
public static final int SHOW_FLOATING_DESKTOP = 42;
public static final int HIDE_FLOATING_DESKTOP = 43;
public static final int OPEN_HIERARCHY_SCREEN = 44;
public static final int SHOW_APP_SHORTCUTS = 45;
public int version = 1;
public EventAction homeKey = new EventAction(GO_HOME_ZOOM_TO_ORIGIN, null);
public EventAction menuKey = new EventAction(SHOW_HIDE_APP_MENU_STATUS_BAR, null);
// update script EventHandler accordingly
public EventAction longMenuKey = EventAction.NOTHING();
public EventAction backKey = new EventAction(BACK, null);
public EventAction longBackKey = EventAction.NOTHING();
public EventAction searchKey = new EventAction(SEARCH, null);
public EventAction itemTap = new EventAction(LAUNCH_ITEM, null);
public EventAction itemLongTap = new EventAction(MOVE_ITEM, null);
public EventAction bgTap = new EventAction(CLOSE_TOPMOST_FOLDER, null);
public EventAction bgDoubleTap = new EventAction(SWITCH_FULL_SCALE_OR_ORIGIN, null);
public EventAction bgLongTap = new EventAction(LAUNCHER_MENU, null);
public EventAction swipeLeft = EventAction.NOTHING();
public EventAction swipeRight = EventAction.NOTHING();
public EventAction swipeUp = EventAction.NOTHING();
public EventAction swipeDown = EventAction.NOTHING();
public EventAction swipe2Left = new EventAction(PREVIOUS_DESKTOP, null);
public EventAction swipe2Right = new EventAction(NEXT_DESKTOP, null);
public EventAction swipe2Up = EventAction.NOTHING();
public EventAction swipe2Down = EventAction.NOTHING();
public EventAction screenOn = EventAction.NOTHING();
public EventAction screenOff = EventAction.NOTHING();
public EventAction orientationPortrait = EventAction.NOTHING();
public EventAction orientationLandscape = EventAction.NOTHING();
public EventAction itemAdded = EventAction.NOTHING();
public EventAction itemRemoved = EventAction.NOTHING();
public EventAction menu = EventAction.NOTHING();
public EventAction startup = EventAction.NOTHING();
public PageAnimation pageAnimation = PageAnimation.FADE;
public int[] screensOrder = null;
public String[] screensNames = null;
public int homeScreen = Page.FIRST_DASHBOARD_PAGE;
public int lockScreen = Page.NONE;
public boolean launchUnlock = true;
public boolean lockDisableOverlay = false;
public boolean runScripts = true;
public int overlayScreen = Page.NONE;
public OverlayHandlePosition overlayShowHandlePosition = OverlayHandlePosition.LEFT_TOP;
public float overlayShowHandleSize = 0.2f;
public float overlayShowHandleWidth = 0.03f;
public OverlayHandlePosition overlayHideHandlePosition = OverlayHandlePosition.RIGHT_MIDDLE;
public float overlayHideHandleSize = 1f;
public float overlayHideHandleWidth = 0.03f;
public OverlayAnimation overlayAnimation = OverlayAnimation.SLIDE;
public boolean overlayDisplayHandles = false;
public boolean overlayLaunchHide = true;
public int lwpScreen = Page.NONE;
public int getPageIndex(int p) {
for (int i = 0; i < screensOrder.length; i++) {
if (screensOrder[i] == p) return i;
}
return 0;
}
public boolean reAddScreenIfNeeded(int p) {
if (!Page.isDashboard(p)) {
return false;
}
int n = screensOrder.length;
for (int i = 0; i < n; i++) {
if (screensOrder[i] == p) return false;
}
int[] newScreensOrder = new int[n + 1];
System.arraycopy(screensOrder, 0, newScreensOrder, 0, n);
newScreensOrder[n] = p;
screensOrder = newScreensOrder;
String[] newScreensNames = new String[n + 1];
System.arraycopy(screensNames, 0, newScreensNames, 0, n);
newScreensNames[n] = String.valueOf(p);
screensNames = newScreensNames;
return true;
}
public enum PageAnimation {
NONE,
FADE,
SLIDE_H,
SLIDE_V
}
public enum OverlayHandlePosition {
LEFT_TOP,
@ -34,139 +158,4 @@ public class GlobalConfig extends JsonLoader {
SLIDE,
FADE
}
public static final int CATEGORY=-1;
public static final int UNSET=0;
public static final int NOTHING=1;
public static final int APP_DRAWER=2;
public static final int ZOOM_FULL_SCALE=3;
public static final int ZOOM_TO_ORIGIN=4;
public static final int SWITCH_FULL_SCALE_OR_ORIGIN=5;
public static final int SHOW_HIDE_STATUS_BAR=6;
public static final int LAUNCHER_MENU=7;
public static final int EDIT_LAYOUT=8;
public static final int CUSTOMIZE_LAUNCHER=9;
public static final int CUSTOMIZE_DESKTOP =10;
public static final int CUSTOMIZE_ITEM=11;
public static final int ITEM_MENU=12;
public static final int LAUNCH_ITEM=13;
public static final int SEARCH=14;
public static final int SHOW_HIDE_APP_MENU=15;
public static final int SHOW_HIDE_APP_MENU_STATUS_BAR=16;
public static final int SHOW_NOTIFICATIONS=17;
public static final int PREVIOUS_DESKTOP =18;
public static final int NEXT_DESKTOP =19;
public static final int LAUNCH_APP=20;
public static final int MOVE_ITEM=21;
public static final int ADD_ITEM=22;
public static final int LAUNCH_SHORTCUT=23;
public static final int SELECT_WALLPAPER=24;
public static final int GO_HOME=25;
public static final int GO_HOME_ZOOM_TO_ORIGIN=26;
public static final int SELECT_DESKTOP_TO_GO_TO=27;
public static final int RESTART=28;
public static final int CLOSE_TOPMOST_FOLDER=29;
public static final int CLOSE_ALL_FOLDERS=30;
public static final int SEARCH_APP=31;
public static final int OPEN_FOLDER=32;
public static final int GO_DESKTOP_POSITION=33;
public static final int UNLOCK_SCREEN=34;
public static final int RUN_SCRIPT=35;
public static final int BACK=36;
public static final int CUSTOM_MENU=37;
public static final int USER_MENU=38;
public static final int WALLPAPER_TAP=39;
public static final int WALLPAPER_SECONDARY_TAP=40;
public static final int SET_VARIABLE=41;
public static final int SHOW_FLOATING_DESKTOP=42;
public static final int HIDE_FLOATING_DESKTOP=43;
public static final int OPEN_HIERARCHY_SCREEN=44;
public static final int SHOW_APP_SHORTCUTS=45;
// update script EventHandler accordingly
public int version=1;
public EventAction homeKey = new EventAction(GO_HOME_ZOOM_TO_ORIGIN, null);
public EventAction menuKey = new EventAction(SHOW_HIDE_APP_MENU_STATUS_BAR, null);
public EventAction longMenuKey = EventAction.NOTHING();
public EventAction backKey = new EventAction(BACK, null);;
public EventAction longBackKey = EventAction.NOTHING();
public EventAction searchKey = new EventAction(SEARCH, null);
public EventAction itemTap = new EventAction(LAUNCH_ITEM, null);
public EventAction itemLongTap = new EventAction(MOVE_ITEM, null);
public EventAction bgTap = new EventAction(CLOSE_TOPMOST_FOLDER, null);
public EventAction bgDoubleTap = new EventAction(SWITCH_FULL_SCALE_OR_ORIGIN, null);
public EventAction bgLongTap = new EventAction(LAUNCHER_MENU, null);
public EventAction swipeLeft = EventAction.NOTHING();
public EventAction swipeRight = EventAction.NOTHING();
public EventAction swipeUp = EventAction.NOTHING();
public EventAction swipeDown = EventAction.NOTHING();
public EventAction swipe2Left = new EventAction(PREVIOUS_DESKTOP, null);
public EventAction swipe2Right = new EventAction(NEXT_DESKTOP, null);
public EventAction swipe2Up = EventAction.NOTHING();
public EventAction swipe2Down = EventAction.NOTHING();
public EventAction screenOn = EventAction.NOTHING();
public EventAction screenOff = EventAction.NOTHING();
public EventAction orientationPortrait = EventAction.NOTHING();
public EventAction orientationLandscape = EventAction.NOTHING();
public EventAction itemAdded = EventAction.NOTHING();
public EventAction itemRemoved = EventAction.NOTHING();
public EventAction menu = EventAction.NOTHING();
public EventAction startup = EventAction.NOTHING();
public PageAnimation pageAnimation=PageAnimation.FADE;
public int[] screensOrder=null;
public String[] screensNames=null;
public int homeScreen= Page.FIRST_DASHBOARD_PAGE;
public int lockScreen= Page.NONE;
public boolean launchUnlock=true;
public boolean lockDisableOverlay=false;
public boolean runScripts=true;
public int overlayScreen = Page.NONE;
public OverlayHandlePosition overlayShowHandlePosition = OverlayHandlePosition.LEFT_TOP;
public float overlayShowHandleSize = 0.2f;
public float overlayShowHandleWidth = 0.03f;
public OverlayHandlePosition overlayHideHandlePosition = OverlayHandlePosition.RIGHT_MIDDLE;
public float overlayHideHandleSize = 1f;
public float overlayHideHandleWidth = 0.03f;
public OverlayAnimation overlayAnimation = OverlayAnimation.SLIDE;
public boolean overlayDisplayHandles = false;
public boolean overlayLaunchHide = true;
public int lwpScreen = Page.NONE;
public int getPageIndex(int p) {
for(int i=0; i<screensOrder.length; i++) {
if(screensOrder[i] == p) return i;
}
return 0;
}
public boolean reAddScreenIfNeeded(int p) {
if(!Page.isDashboard(p)) {
return false;
}
int n = screensOrder.length;
for(int i=0; i<n; i++) {
if(screensOrder[i] == p) return false;
}
int[] newScreensOrder = new int[n+1];
System.arraycopy(screensOrder, 0, newScreensOrder, 0, n);
newScreensOrder[n] = p;
screensOrder = newScreensOrder;
String[] newScreensNames = new String[n+1];
System.arraycopy(screensNames, 0, newScreensNames, 0, n);
newScreensNames[n] = String.valueOf(p);
screensNames = newScreensNames;
return true;
}
}

View file

@ -1,7 +1,9 @@
package net.pierrox.lightning_launcher.configuration;
public interface ItemConfigStylable {
public ItemConfig getItemConfig();
public void setItemConfig(ItemConfig c);
public ItemConfig modifyItemConfig();
ItemConfig getItemConfig();
void setItemConfig(ItemConfig c);
ItemConfig modifyItemConfig();
}

View file

@ -24,77 +24,90 @@ import java.io.File;
public class ShortcutConfig extends JsonLoader {
private static final PorterDuffXfermode sMaskXferMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
private static final class CachedTypeface {
String path;
Typeface typeface;
}
private static CachedTypeface sCachedTypefaces[]=new CachedTypeface[15];
public enum LabelVsIconPosition {
LEFT,
TOP,
RIGHT,
BOTTOM,
CENTER
}
public enum FontStyle {
NORMAL,
BOLD,
ITALIC,
BOLD_ITALIC
}
public enum IconSizeMode {
STANDARD,
REAL,
FULL_SCALE_RATIO,
FULL_SCALE,
NORMALIZED,
}
public boolean labelVisibility=true;
public int labelFontColor=Color.WHITE;
public float labelFontSize=12f;
public String labelFontTypeFace=API.SHORTCUT_SYSTEM_FONT;
public FontStyle labelFontStyle=FontStyle.NORMAL;
public int labelMaxLines=1;
public boolean iconVisibility=true;
public IconSizeMode iconSizeMode=IconSizeMode.STANDARD;
public float iconScale=1.0f;
public boolean iconReflection=false;
public float iconReflectionOverlap=0.3f;
public float iconReflectionSize=1f; // % of the reflection size, amount of visible reflection
public float iconReflectionScale=1f;
public boolean iconFilter=false;
public ShortcutConfig.LabelVsIconPosition labelVsIconPosition=LabelVsIconPosition.BOTTOM;
public int labelVsIconMargin=4;
public int selectionColorLabel=Color.WHITE;
public int focusColorLabel=0xffccccff;
public boolean labelShadow=true;
public float labelShadowRadius=3;
public float labelShadowOffsetX=1;
public float labelShadowOffsetY=1;
public int labelShadowColor=0xaa000000;
public float iconEffectScale=1f;
public int iconColorFilter=0xffffffff;
private static final CachedTypeface[] sCachedTypefaces = new CachedTypeface[15];
public boolean labelVisibility = true;
public int labelFontColor = Color.WHITE;
public float labelFontSize = 12f;
public String labelFontTypeFace = API.SHORTCUT_SYSTEM_FONT;
public FontStyle labelFontStyle = FontStyle.NORMAL;
public int labelMaxLines = 1;
public boolean iconVisibility = true;
public IconSizeMode iconSizeMode = IconSizeMode.STANDARD;
public float iconScale = 1.0f;
public boolean iconReflection = false;
public float iconReflectionOverlap = 0.3f;
public float iconReflectionSize = 1f; // % of the reflection size, amount of visible reflection
public float iconReflectionScale = 1f;
public boolean iconFilter = false;
public ShortcutConfig.LabelVsIconPosition labelVsIconPosition = LabelVsIconPosition.BOTTOM;
public int labelVsIconMargin = 4;
public int selectionColorLabel = Color.WHITE;
public int focusColorLabel = 0xffccccff;
public boolean labelShadow = true;
public float labelShadowRadius = 3;
public float labelShadowOffsetX = 1;
public float labelShadowOffsetY = 1;
public int labelShadowColor = 0xaa000000;
public float iconEffectScale = 1f;
public int iconColorFilter = 0xffffffff;
public Drawable iconBack, iconOver, iconMask;
public static ShortcutConfig readFromJsonObject(JSONObject o, ShortcutConfig d) throws JSONException {
ShortcutConfig c=new ShortcutConfig();
c.loadFieldsFromJSONObject(o, d);
ShortcutConfig c = new ShortcutConfig();
c.loadFieldsFromJSONObject(o, d);
c.iconBack = d.iconBack;
c.iconOver = d.iconOver;
c.iconMask = d.iconMask;
return c;
}
return c;
}
public static File getIconBackFile(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_ICON_BACK);
}
public static File getIconOverFile(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_ICON_OVER);
}
public static File getIconMaskFile(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_ICON_MASK);
}
private static Typeface getTypeFace(String font_path) {
if (API.SHORTCUT_SYSTEM_FONT.equals(font_path)) {
return null;
}
if (API.SHORTCUT_ICON_FONT.equals(font_path)) {
return LLApp.get().getIconsTypeface();
}
CachedTypeface ctf = null;
int l = sCachedTypefaces.length;
int i;
for (i = 0; i < l; i++) {
ctf = sCachedTypefaces[i];
if (ctf == null) break;
if (ctf.path.equals(font_path)) return ctf.typeface;
}
if (i < l) {
ctf = new CachedTypeface();
ctf.path = font_path;
try {
ctf.typeface = Typeface.createFromFile(font_path);
sCachedTypefaces[i] = ctf;
return ctf.typeface;
} catch (Exception e) {
return null;
}
} else {
return null;
}
}
@Override
public ShortcutConfig clone() {
@ -106,7 +119,7 @@ public class ShortcutConfig extends JsonLoader {
@Override
public void copyFrom(JsonLoader o) {
super.copyFrom(o);
ShortcutConfig sc = (ShortcutConfig)o;
ShortcutConfig sc = (ShortcutConfig) o;
iconBack = sc.iconBack;
iconOver = sc.iconOver;
iconMask = sc.iconMask;
@ -114,39 +127,35 @@ public class ShortcutConfig extends JsonLoader {
public void loadAssociatedIcons(File icon_dir, int id) {
File f = getIconBackFile(icon_dir, id);
if(f.exists()) iconBack=Utils.loadDrawable(f);
if (f.exists()) iconBack = Utils.loadDrawable(f);
f = getIconOverFile(icon_dir, id);
if(f.exists()) iconOver=Utils.loadDrawable(f);
if (f.exists()) iconOver = Utils.loadDrawable(f);
f = getIconMaskFile(icon_dir, id);
if(f.exists()) {
if (f.exists()) {
SharedAsyncGraphicsDrawable d = Utils.loadDrawable(f);
iconMask = d;
if(d != null && d.getType() == SharedAsyncGraphicsDrawable.TYPE_BITMAP) {
if (d != null && d.getType() == SharedAsyncGraphicsDrawable.TYPE_BITMAP) {
d.getPaint().setXfermode(sMaskXferMode);
}
}
}
public static File getIconBackFile(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_ICON_BACK);
}
public static File getIconOverFile(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_ICON_OVER);
}
public static File getIconMaskFile(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_ICON_MASK);
}
public void applyFontStyleToTextView(MyTextView tv) {
Typeface tf=getTypeFace(labelFontTypeFace);
Typeface tf = getTypeFace(labelFontTypeFace);
int s;
switch(labelFontStyle) {
case BOLD: s=Typeface.BOLD; break;
case BOLD_ITALIC: s=Typeface.BOLD_ITALIC; break;
case ITALIC: s=Typeface.ITALIC; break;
default: s=Typeface.NORMAL; break;
switch (labelFontStyle) {
case BOLD:
s = Typeface.BOLD;
break;
case BOLD_ITALIC:
s = Typeface.BOLD_ITALIC;
break;
case ITALIC:
s = Typeface.ITALIC;
break;
default:
s = Typeface.NORMAL;
break;
}
tv.setTypeface(tf, s);
}
@ -157,55 +166,56 @@ public class ShortcutConfig extends JsonLoader {
applyFontStyleToTextView(tv);
//tv.setIncludeFontPadding(false);
tv.setEllipsize(TextUtils.TruncateAt.END);
if(labelMaxLines==1) {
if (labelMaxLines == 1) {
tv.setSingleLine();
} else {
tv.setSingleLine(false);
tv.setMaxLines(labelMaxLines);
int g;
switch(ic.box.ah) {
case LEFT: g= Gravity.LEFT; break;
case RIGHT: g=Gravity.RIGHT; break;
default: g=Gravity.CENTER; break;
switch (ic.box.ah) {
case LEFT:
g = Gravity.LEFT;
break;
case RIGHT:
g = Gravity.RIGHT;
break;
default:
g = Gravity.CENTER;
break;
}
tv.setGravity(g);
}
if(labelShadow) {
if (labelShadow) {
tv.setShadowLayer(labelShadowRadius, labelShadowOffsetX, labelShadowOffsetY, labelShadowColor);
}
tv.setfixWidth(labelShadow || labelFontStyle== ShortcutConfig.FontStyle.ITALIC || labelFontStyle== ShortcutConfig.FontStyle.BOLD_ITALIC);
tv.setfixWidth(labelShadow || labelFontStyle == ShortcutConfig.FontStyle.ITALIC || labelFontStyle == ShortcutConfig.FontStyle.BOLD_ITALIC);
}
private static Typeface getTypeFace(String font_path) {
if(API.SHORTCUT_SYSTEM_FONT.equals(font_path)) {
return null;
}
public enum LabelVsIconPosition {
LEFT,
TOP,
RIGHT,
BOTTOM,
CENTER
}
if(API.SHORTCUT_ICON_FONT.equals(font_path)) {
return LLApp.get().getIconsTypeface();
}
public enum FontStyle {
NORMAL,
BOLD,
ITALIC,
BOLD_ITALIC
}
CachedTypeface ctf=null;
int l=sCachedTypefaces.length;
int i;
for(i=0; i<l; i++) {
ctf=sCachedTypefaces[i];
if(ctf==null) break;
if(ctf.path.equals(font_path)) return ctf.typeface;
}
public enum IconSizeMode {
STANDARD,
REAL,
FULL_SCALE_RATIO,
FULL_SCALE,
NORMALIZED,
}
if(i<l) {
ctf=new CachedTypeface();
ctf.path=font_path;
try {
ctf.typeface=Typeface.createFromFile(font_path);
sCachedTypefaces[i]=ctf;
return ctf.typeface;
} catch(Exception e) {
return null;
}
} else {
return null;
}
private static final class CachedTypeface {
String path;
Typeface typeface;
}
}

View file

@ -1,7 +1,9 @@
package net.pierrox.lightning_launcher.configuration;
public interface ShortcutConfigStylable {
public ShortcutConfig getShortcutConfig();
public void setShortcutConfig(ShortcutConfig c);
public ShortcutConfig modifyShortcutConfig();
ShortcutConfig getShortcutConfig();
void setShortcutConfig(ShortcutConfig c);
ShortcutConfig modifyShortcutConfig();
}

View file

@ -4,194 +4,193 @@ import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import net.pierrox.android.lsvg.SvgDrawable;
import net.pierrox.lightning_launcher.util.AnimationDecoder;
import net.pierrox.lightning_launcher.views.Graphics;
import net.pierrox.lightning_launcher.views.SharedAsyncGraphicsDrawable;
import net.pierrox.android.lsvg.SvgDrawable;
import java.io.File;
public class Box implements SharedAsyncGraphicsDrawable.GraphicsProvider {
public enum AlignH {
LEFT,
CENTER,
RIGHT,
CUSTOM
}
public enum AlignV {
TOP,
MIDDLE,
BOTTOM,
CUSTOM
}
public static final int ML=0;
public static final int MT=1;
public static final int MR=2;
public static final int MB=3;
public static final int BL=4;
public static final int BT=5;
public static final int BR=6;
public static final int BB=7;
public static final int PL=8;
public static final int PT=9;
public static final int PR=10;
public static final int PB=11;
public static final int BCL=0;
public static final int BCT=1;
public static final int BCR=2;
public static final int BCB=3;
public static final int COLOR_SHIFT_N=0;
public static final int COLOR_SHIFT_S=4;
public static final int COLOR_SHIFT_F=8;
public int[] size;
public int[] border_color;
// color content normal/pressed/focused
public int ccn=Color.TRANSPARENT;
public int ccs=0xffffffff;
public int ccf=0x808080ff;
// align h/v
public AlignH ah=AlignH.CENTER;
public AlignV av=AlignV.MIDDLE;
public static final int ML = 0;
public static final int MT = 1;
public static final int MR = 2;
public static final int MB = 3;
public static final int BL = 4;
public static final int BT = 5;
public static final int BR = 6;
public static final int BB = 7;
public static final int PL = 8;
public static final int PT = 9;
public static final int PR = 10;
public static final int PB = 11;
public static final int BCL = 0;
public static final int BCT = 1;
public static final int BCR = 2;
public static final int BCB = 3;
public static final int COLOR_SHIFT_N = 0;
public static final int COLOR_SHIFT_S = 4;
public static final int COLOR_SHIFT_F = 8;
private static final StringBuffer sTmpStringBuffer = new StringBuffer(200);
public int[] size;
public int[] border_color;
// color content normal/pressed/focused
public int ccn = Color.TRANSPARENT;
public int ccs = 0xffffffff;
public int ccf = 0x808080ff;
// align h/v
public AlignH ah = AlignH.CENTER;
public AlignV av = AlignV.MIDDLE;
public Drawable bgNormal;
public Drawable bgSelected;
public Drawable bgFocused;
public Drawable bgFolder;
public Box() {
size = new int[12];
border_color = new int[12];
for(int i=0; i<border_color.length; i++) border_color[i] = Color.WHITE;
}
public void loadFromString(String s, Box d) {
String[] e=s.split(":");
public Box() {
size = new int[12];
border_color = new int[12];
for (int i = 0; i < border_color.length; i++) border_color[i] = Color.WHITE;
}
try {
loadArray(e, 0, size, d.size);
loadArray(e, 12, border_color, d.border_color);
String v;
v=getStringAt(e, 24); ccn=v==null ? d.ccn : Integer.parseInt(v);
v=getStringAt(e, 25); ccs=v==null ? d.ccs : Integer.parseInt(v);
v=getStringAt(e, 26); ccf=v==null ? d.ccf : Integer.parseInt(v);
v=getStringAt(e, 27); ah=v==null ? d.ah : AlignH.valueOf(v);
v=getStringAt(e, 28); av=v==null ? d.av : AlignV.valueOf(v);
} catch(Exception e1) {
// pass
}
}
public static File getBoxBackgroundNormal(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_BOX_BG_NORMAL);
}
public static File getBoxBackgroundSelected(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_BOX_BG_SELECTED);
}
public static File getBoxBackgroundFocused(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_BOX_BG_FOCUSED);
}
public static File getBoxBackgroundFolder(File icon_dir, int id) {
return new File(icon_dir, (id == Item.NO_ID ? "" : id) + FileUtils.SUFFIX_BOX_BG_FOLDER);
}
private static String getStringAt(String[] e, int i) {
if (i < e.length) {
String v = e[i];
return v.length() == 0 ? null : v;
} else {
return null;
}
}
public void loadFromString(String s, Box d) {
String[] e = s.split(":");
try {
loadArray(e, 0, size, d.size);
loadArray(e, 12, border_color, d.border_color);
String v;
v = getStringAt(e, 24);
ccn = v == null ? d.ccn : Integer.parseInt(v);
v = getStringAt(e, 25);
ccs = v == null ? d.ccs : Integer.parseInt(v);
v = getStringAt(e, 26);
ccf = v == null ? d.ccf : Integer.parseInt(v);
v = getStringAt(e, 27);
ah = v == null ? d.ah : AlignH.valueOf(v);
v = getStringAt(e, 28);
av = v == null ? d.av : AlignV.valueOf(v);
} catch (Exception e1) {
// pass
}
}
public void loadAssociatedDrawables(File icon_dir, int id, boolean for_item) {
File f;
if(for_item) {
if (for_item) {
f = getBoxBackgroundNormal(icon_dir, id);
if(f.exists()) bgNormal = new SharedAsyncGraphicsDrawable(this, f, true);
if (f.exists()) bgNormal = new SharedAsyncGraphicsDrawable(this, f, true);
f = getBoxBackgroundSelected(icon_dir, id);
if(f.exists()) bgSelected = new SharedAsyncGraphicsDrawable(this, f, true);
if (f.exists()) bgSelected = new SharedAsyncGraphicsDrawable(this, f, true);
f = getBoxBackgroundFocused(icon_dir, id);
if(f.exists()) bgFocused = new SharedAsyncGraphicsDrawable(this, f, true);
if (f.exists()) bgFocused = new SharedAsyncGraphicsDrawable(this, f, true);
} else {
f = getBoxBackgroundFolder(icon_dir, id);
if(f.exists()) bgFolder = new SharedAsyncGraphicsDrawable(this, f, true);
if (f.exists()) bgFolder = new SharedAsyncGraphicsDrawable(this, f, true);
}
}
@Override
public Graphics provideGraphics(SharedAsyncGraphicsDrawable sbd, Object data, int max_width, int max_height) {
File file = (File) data;
Graphics graphics = null;
if(Utils.isGifFile(file)) {
AnimationDecoder animationDecoder = Utils.loadGifDecoder(file);
graphics = animationDecoder == null ? null : new Graphics(animationDecoder, 0, 0);
} else if(Utils.isSvgFile(file)) {
SvgDrawable svgDrawable = new SvgDrawable(file);
graphics = new Graphics(svgDrawable);
}
if(graphics == null) {
Bitmap bitmap = Utils.loadBitmap((File) data, 0, max_width, max_height);
graphics = bitmap == null ? null : new Graphics(bitmap);
}
return graphics;
File file = (File) data;
Graphics graphics = null;
if (Utils.isGifFile(file)) {
AnimationDecoder animationDecoder = Utils.loadGifDecoder(file);
graphics = animationDecoder == null ? null : new Graphics(animationDecoder, 0, 0);
} else if (Utils.isSvgFile(file)) {
SvgDrawable svgDrawable = new SvgDrawable(file);
graphics = new Graphics(svgDrawable);
}
if (graphics == null) {
Bitmap bitmap = Utils.loadBitmap((File) data, 0, max_width, max_height);
graphics = bitmap == null ? null : new Graphics(bitmap);
}
return graphics;
}
@Override
public boolean composeGraphics(Bitmap baseIcon, Bitmap finalIcon) {
return false;
}
public static File getBoxBackgroundNormal(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_BOX_BG_NORMAL);
@Override
public boolean composeGraphics(Bitmap baseIcon, Bitmap finalIcon) {
return false;
}
public static File getBoxBackgroundSelected(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_BOX_BG_SELECTED);
private void loadArray(String[] e, int offset, int[] dst, int[] dst_def) {
int n = dst.length;
for (int i = 0; i < n; i++) {
String v = getStringAt(e, i + offset);
dst[i] = v == null ? dst_def[i] : Integer.parseInt(v);
}
}
public static File getBoxBackgroundFocused(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_BOX_BG_FOCUSED);
public String toString(Box d) {
sTmpStringBuffer.setLength(0);
appendArray(size, d == null ? null : d.size);
appendArray(border_color, d == null ? null : d.border_color);
if (d == null || d.ccn != ccn) sTmpStringBuffer.append(ccn);
sTmpStringBuffer.append(':');
if (d == null || d.ccs != ccs) sTmpStringBuffer.append(ccs);
sTmpStringBuffer.append(':');
if (d == null || d.ccf != ccf) sTmpStringBuffer.append(ccf);
sTmpStringBuffer.append(':');
if (d == null || d.ah != ah) sTmpStringBuffer.append(ah.toString());
sTmpStringBuffer.append(':');
if (d == null || d.av != av) sTmpStringBuffer.append(av.toString());
sTmpStringBuffer.append(':');
return sTmpStringBuffer.toString();
}
public static File getBoxBackgroundFolder(File icon_dir, int id) {
return new File(icon_dir, (id== Item.NO_ID?"":id)+FileUtils.SUFFIX_BOX_BG_FOLDER);
private void appendArray(int[] src, int[] src_def) {
int n = src.length;
for (int i = 0; i < n; i++) {
int v = src[i];
if (src_def == null || v != src_def[i]) sTmpStringBuffer.append(v);
sTmpStringBuffer.append(':');
}
}
private static String getStringAt(String e[], int i) {
if(i<e.length) {
String v = e[i];
return v.length() == 0 ? null : v;
} else {
return null;
}
}
private void loadArray(String[] e, int offset, int[] dst, int[] dst_def) {
int n = dst.length;
for(int i=0; i<n; i++) {
String v = getStringAt(e, i+offset);
dst[i] = v==null ? dst_def[i] : Integer.parseInt(v);
}
}
public enum AlignH {
LEFT,
CENTER,
RIGHT,
CUSTOM
}
public String toString(Box d) {
sTmpStringBuffer.setLength(0);
appendArray(size, d==null ? null : d.size);
appendArray(border_color, d==null ? null : d.border_color);
if(d==null || d.ccn!=ccn) sTmpStringBuffer.append(ccn);
sTmpStringBuffer.append(':');
if(d==null ||d.ccs!=ccs) sTmpStringBuffer.append(ccs);
sTmpStringBuffer.append(':');
if(d==null ||d.ccf!=ccf) sTmpStringBuffer.append(ccf);
sTmpStringBuffer.append(':');
if(d==null ||d.ah!=ah) sTmpStringBuffer.append(ah.toString());
sTmpStringBuffer.append(':');
if(d==null ||d.av!=av) sTmpStringBuffer.append(av.toString());
sTmpStringBuffer.append(':');
return sTmpStringBuffer.toString();
}
private void appendArray(int[] src, int[] src_def) {
int n = src.length;
for(int i=0; i<n; i++) {
int v = src[i];
if(src_def==null || v!=src_def[i]) sTmpStringBuffer.append(v);
sTmpStringBuffer.append(':');
}
}
private static StringBuffer sTmpStringBuffer=new StringBuffer(200);
public enum AlignV {
TOP,
MIDDLE,
BOTTOM,
CUSTOM
}
}

View file

@ -7,73 +7,73 @@ public class ContainerPath {
// 0 page 0
// 0/2 page 0, container for item 2
protected String mPath;
protected String mPath;
public ContainerPath(String path) {
mPath = path;
public ContainerPath(String path) {
mPath = path;
}
public ContainerPath(int page) {
mPath = String.valueOf(page);
}
public ContainerPath(ItemView iv) {
StringBuilder path = new StringBuilder();
build(iv, path);
mPath = path.toString();
}
public ContainerPath(ItemLayout il) {
StringBuilder path = new StringBuilder();
build(il, path);
mPath = path.toString();
}
private void build(ItemView iv, StringBuilder out) {
Item item = iv.getItem();
ItemView openerItemView = iv.getParentItemLayout().getOpenerItemView();
if (openerItemView == null) {
out.append(item.getPage().id);
} else {
build(openerItemView, out);
}
out.append('/');
out.append(item.getId());
}
public ContainerPath(int page) {
mPath = String.valueOf(page);
private void build(ItemLayout il, StringBuilder out) {
ItemView opener = il.getOpenerItemView();
if (opener != null) {
build(opener.getParentItemLayout(), out);
} else {
out.append(il.getPage().id);
}
public ContainerPath(ItemView iv) {
StringBuilder path = new StringBuilder();
build(iv, path);
mPath = path.toString();
}
public ContainerPath(ItemLayout il) {
StringBuilder path = new StringBuilder();
build(il, path);
mPath = path.toString();
}
private void build(ItemView iv, StringBuilder out) {
Item item = iv.getItem();
ItemView openerItemView = iv.getParentItemLayout().getOpenerItemView();
if(openerItemView == null) {
out.append(item.getPage().id);
} else {
build(openerItemView, out);
}
if (opener != null) {
out.append('/');
out.append(item.getId());
out.append(opener.getItem().getId());
}
}
private void build(ItemLayout il, StringBuilder out) {
ItemView opener = il.getOpenerItemView();
if(opener != null) {
build(opener.getParentItemLayout(), out);
} else {
out.append(il.getPage().id);
}
if(opener != null) {
out.append('/');
out.append(opener.getItem().getId());
}
public ContainerPath getParent() {
int pos = mPath.lastIndexOf('/');
if (pos == -1) {
return null;
} else {
return new ContainerPath(mPath.substring(0, pos));
}
}
public ContainerPath getParent() {
int pos = mPath.lastIndexOf('/', mPath.length()-1);
if(pos == -1) {
return null;
} else {
return new ContainerPath(mPath.substring(0, pos));
}
}
public int getLast() {
return Integer.parseInt(mPath.substring(mPath.lastIndexOf('/') + 1));
}
public int getLast() {
return Integer.parseInt(mPath.substring(mPath.lastIndexOf('/')+1));
}
@Override
public boolean equals(Object o) {
return o instanceof ContainerPath && mPath.equals(((ContainerPath) o).mPath);
}
@Override
public boolean equals(Object o) {
return o instanceof ContainerPath && mPath.equals(((ContainerPath)o).mPath);
}
@Override
public String toString() {
return mPath;
}
}
@Override
public String toString() {
return mPath;
}
}

View file

@ -1,7 +1,16 @@
package net.pierrox.lightning_launcher.data;
import android.accounts.*;
import android.content.*;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Rect;
@ -13,10 +22,10 @@ import android.os.StatFs;
import android.provider.CallLog;
import android.text.format.Formatter;
import net.pierrox.lightning_launcher.R;
import net.pierrox.lightning_launcher.configuration.DynamicTextConfig;
import net.pierrox.lightning_launcher.configuration.JsonFields;
import net.pierrox.lightning_launcher.configuration.ShortcutConfig;
import net.pierrox.lightning_launcher.R;
import net.pierrox.lightning_launcher.views.item.ItemView;
import net.pierrox.lightning_launcher.views.item.ShortcutView;
@ -55,6 +64,35 @@ public class DynamicText extends Shortcut {
super(page);
}
public static ComponentName getDefaultComponentNameForSource(DynamicTextConfig.Source source) {
String cn = null;
switch (source) {
case MISSED_CALLS:
cn = "com.android.contacts/.DialtactsActivity";
break;
case UNREAD_SMS:
cn = "com.android.mms/.ui.ConversationList";
break;
case UNREAD_GMAIL:
cn = "com.google.android.gm/.ConversationListActivityGmail";
break;
case DATE:
cn = "com.google.android.deskclock/com.android.deskclock.DeskClock";
break;
case STORAGE:
cn = "com.android.settings/.Settings";
break;
case BATTERY_LEVEL:
cn = "com.android.settings/.BatteryInfo";
break;
case HEAP_FREE:
case HEAP_MAX:
cn = "com.android.settings/.Settings";
break;
}
return ComponentName.unflattenFromString(cn);
}
public DynamicTextConfig getDynamicTextConfig() {
return mDynamicTextConfig;
}
@ -72,10 +110,10 @@ public class DynamicText extends Shortcut {
@Override
public void createFromJSONObject(JSONObject o) throws JSONException {
JSONObject json_configuration=o.optJSONObject(JsonFields.DYNAMIC_TEXT_CONFIGURATION);
JSONObject json_configuration = o.optJSONObject(JsonFields.DYNAMIC_TEXT_CONFIGURATION);
DynamicTextConfig defaultDynamicTextConfig = mPage.config.defaultDynamicTextConfig;
if(json_configuration!=null) {
mDynamicTextConfig=DynamicTextConfig.readFromJsonObject(json_configuration, defaultDynamicTextConfig);
if (json_configuration != null) {
mDynamicTextConfig = DynamicTextConfig.readFromJsonObject(json_configuration, defaultDynamicTextConfig);
} else {
mDynamicTextConfig = defaultDynamicTextConfig;
}
@ -89,10 +127,10 @@ public class DynamicText extends Shortcut {
Intent intent = new Intent();
intent.setComponent(getDefaultComponentNameForSource(source));
super.init(id, cell_p, cell_l, "", intent);
mShortcutConfig=new ShortcutConfig();
mShortcutConfig = new ShortcutConfig();
mShortcutConfig.iconVisibility = false;
mSharedShortcutConfig=false;
mDynamicTextConfig=new DynamicTextConfig();
mSharedShortcutConfig = false;
mDynamicTextConfig = new DynamicTextConfig();
mDynamicTextConfig.source = source;
}
@ -103,13 +141,13 @@ public class DynamicText extends Shortcut {
private void create() {
final Context context = mPage.getEngine().getContext();
switch(mDynamicTextConfig.source) {
switch (mDynamicTextConfig.source) {
case DATE:
mHandler = new Handler();
try {
mDateFormat = new SimpleDateFormat(mDynamicTextConfig.dateFormat);
} catch (IllegalArgumentException e) {
mDateFormat = new SimpleDateFormat("'"+context.getString(R.string.dt_format_error)+"'");
mDateFormat = new SimpleDateFormat("'" + context.getString(R.string.dt_format_error) + "'");
}
break;
@ -121,12 +159,12 @@ public class DynamicText extends Shortcut {
case BATTERY_LEVEL:
mBatteryContext = context.getApplicationContext();
mBatteryReceiver=new BroadcastReceiver() {
mBatteryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int new_level=intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
if(new_level!=mBatteryLevel) {
mBatteryLevel=new_level;
int new_level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
if (new_level != mBatteryLevel) {
mBatteryLevel = new_level;
updateText();
}
}
@ -134,7 +172,7 @@ public class DynamicText extends Shortcut {
try {
mCountFormat = new DecimalFormat(mDynamicTextConfig.countFormat);
} catch (IllegalArgumentException e) {
mCountFormat = new DecimalFormat("'"+context.getString(R.string.dt_format_error)+"'");
mCountFormat = new DecimalFormat("'" + context.getString(R.string.dt_format_error) + "'");
}
break;
@ -144,11 +182,11 @@ public class DynamicText extends Shortcut {
try {
mCountFormat = new DecimalFormat(mDynamicTextConfig.countFormat);
} catch (IllegalArgumentException e) {
mCountFormat = new DecimalFormat("'"+context.getString(R.string.dt_format_error)+"'");
mCountFormat = new DecimalFormat("'" + context.getString(R.string.dt_format_error) + "'");
}
mHandler = new Handler();
mContentObserver=new ContentObserver(mHandler) {
mContentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
updateText();
@ -157,13 +195,13 @@ public class DynamicText extends Shortcut {
mCursor = null;
try {
switch(mDynamicTextConfig.source) {
switch (mDynamicTextConfig.source) {
case MISSED_CALLS:
String[] projection = { CallLog.Calls.CACHED_NAME, CallLog.Calls.CACHED_NUMBER_LABEL, CallLog.Calls.TYPE };
String where = CallLog.Calls.TYPE+"="+CallLog.Calls.MISSED_TYPE+" and "+CallLog.Calls.NEW+"=1";
String[] projection = {CallLog.Calls.CACHED_NAME, CallLog.Calls.CACHED_NUMBER_LABEL, CallLog.Calls.TYPE};
String where = CallLog.Calls.TYPE + "=" + CallLog.Calls.MISSED_TYPE + " and " + CallLog.Calls.NEW + "=1";
try {
mCursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, projection, where, null, null);
} catch(SecurityException e) {
} catch (SecurityException e) {
mPage.onItemError(this, Error.MISSING_PERMISSION_READ_CALL_LOG);
}
break;
@ -172,13 +210,13 @@ public class DynamicText extends Shortcut {
Uri sms_content = Uri.parse("content://sms");
try {
mCursor = context.getContentResolver().query(sms_content, null, "read = 0", null, null);
} catch(SecurityException e) {
} catch (SecurityException e) {
mPage.onItemError(this, Error.MISSING_PERMISSION_READ_SMS);
}
break;
case UNREAD_GMAIL:
if(GmailContract.canReadLabels(context)) {
if (GmailContract.canReadLabels(context)) {
AccountManager.get(context).getAccountsByTypeAndFeatures(GmailContract.ACCOUNT_TYPE_GOOGLE, GmailContract.FEATURES_MAIL,
new AccountManagerCallback<Account[]>() {
@Override
@ -196,11 +234,11 @@ public class DynamicText extends Shortcut {
}, null /* handler */);
}
}
} catch(Exception e) {
} catch (Exception e) {
e.printStackTrace();
}
if(mCursor != null) {
if (mCursor != null) {
setupMessagingCursor();
}
break;
@ -212,8 +250,8 @@ public class DynamicText extends Shortcut {
@Override
public void pause() {
super.pause();
if(!mCreated) return;
switch(mDynamicTextConfig.source) {
if (!mCreated) return;
switch (mDynamicTextConfig.source) {
case DATE:
case STORAGE:
case HEAP_FREE:
@ -241,12 +279,12 @@ public class DynamicText extends Shortcut {
@Override
public void resume() {
super.resume();
if(!mCreated) {
if (!mCreated) {
create();
}
// Log.i("XXX", "DT resume "+mId);
switch(mDynamicTextConfig.source) {
switch (mDynamicTextConfig.source) {
case DATE:
case STORAGE:
case HEAP_FREE:
@ -273,7 +311,6 @@ public class DynamicText extends Shortcut {
super.resume();
}
@Override
public void onCreate() {
super.onCreate();
@ -282,10 +319,10 @@ public class DynamicText extends Shortcut {
@Override
public void onDestroy() {
if(!mCreated) return;
if (!mCreated) return;
// Log.i("XXX", "DT destroy " + mId);
if(mCursor != null) {
if (mCursor != null) {
mCursor.close();
}
@ -297,34 +334,11 @@ public class DynamicText extends Shortcut {
super.onDestroy();
}
public static ComponentName getDefaultComponentNameForSource(DynamicTextConfig.Source source) {
String cn = null;
switch(source) {
case MISSED_CALLS: cn="com.android.contacts/.DialtactsActivity"; break;
case UNREAD_SMS: cn="com.android.mms/.ui.ConversationList"; break;
case UNREAD_GMAIL: cn="com.google.android.gm/.ConversationListActivityGmail"; break;
case DATE: cn="com.google.android.deskclock/com.android.deskclock.DeskClock"; break;
case STORAGE: cn="com.android.settings/.Settings"; break;
case BATTERY_LEVEL: cn="com.android.settings/.BatteryInfo"; break;
case HEAP_FREE:
case HEAP_MAX: cn="com.android.settings/.Settings"; break;
}
return ComponentName.unflattenFromString(cn);
}
public void setEditMode(boolean edit_mode) {
mEditMode = edit_mode;
updateVisibility();
}
private Runnable mTimerRunnable = new Runnable() {
@Override
public void run() {
updateText();
mHandler.postDelayed(mTimerRunnable, 1000);
}
};
private void onAccountResults(Context context, Account[] accounts) {
if (accounts != null && accounts.length > 0) {
try {
@ -349,13 +363,21 @@ public class DynamicText extends Shortcut {
setupMessagingCursor();
}
}
} catch(Exception e) {
} catch (Exception e) {
// pass
e.printStackTrace();
}
}
}
private final Runnable mTimerRunnable = new Runnable() {
@Override
public void run() {
updateText();
mHandler.postDelayed(mTimerRunnable, 1000);
}
};
private void setupMessagingCursor() {
mCursor.registerContentObserver(mContentObserver);
updateText();
@ -365,9 +387,9 @@ public class DynamicText extends Shortcut {
String new_text = null;
switch(mDynamicTextConfig.source) {
switch (mDynamicTextConfig.source) {
case DATE:
if(mDateFormat == null) {
if (mDateFormat == null) {
mDateFormat = new SimpleDateFormat(DynamicTextConfig.DEFAULT_DATE_FORMAT);
}
new_text = mDateFormat.format(new Date());
@ -380,29 +402,34 @@ public class DynamicText extends Shortcut {
long total_blocks = stat.getBlockCount();
long available_blocks = stat.getAvailableBlocks();
long value;
switch(mDynamicTextConfig.storageWhat) {
case LEFT: value = available_blocks; break;
case USED: value = total_blocks-available_blocks; break;
default: value = total_blocks;
switch (mDynamicTextConfig.storageWhat) {
case LEFT:
value = available_blocks;
break;
case USED:
value = total_blocks - available_blocks;
break;
default:
value = total_blocks;
}
value *= block_size;
switch(mDynamicTextConfig.storageFormat) {
case NORMAL:
new_text = Formatter.formatFileSize(mPage.getEngine().getContext(), value);
break;
switch (mDynamicTextConfig.storageFormat) {
case NORMAL:
new_text = Formatter.formatFileSize(mPage.getEngine().getContext(), value);
break;
case SHORT:
new_text = Formatter.formatShortFileSize(mPage.getEngine().getContext(), value);
break;
case SHORT:
new_text = Formatter.formatShortFileSize(mPage.getEngine().getContext(), value);
break;
case PERCENT:
new_text = String.valueOf(value*100 / (total_blocks*block_size))+"%";
break;
case PERCENT:
new_text = value * 100 / (total_blocks * block_size) + "%";
break;
case BYTES:
default:
new_text = String.valueOf(value);
break;
case BYTES:
default:
new_text = String.valueOf(value);
break;
}
new_text = mDynamicTextConfig.textFormat.replace("%s", new_text);
break;
@ -411,7 +438,7 @@ public class DynamicText extends Shortcut {
case HEAP_MAX:
Runtime r = Runtime.getRuntime();
long m = r.maxMemory();
if(mDynamicTextConfig.source== DynamicTextConfig.Source.HEAP_FREE) {
if (mDynamicTextConfig.source == DynamicTextConfig.Source.HEAP_FREE) {
r.gc();
m -= (r.totalMemory() - r.freeMemory());
}
@ -423,8 +450,8 @@ public class DynamicText extends Shortcut {
case UNREAD_SMS:
case UNREAD_GMAIL:
mCount = 0;
if(mDynamicTextConfig.source== DynamicTextConfig.Source.UNREAD_GMAIL) {
if(mGMailInboxUri != null) {
if (mDynamicTextConfig.source == DynamicTextConfig.Source.UNREAD_GMAIL) {
if (mGMailInboxUri != null) {
Cursor c = mPage.getEngine().getContext().getContentResolver().query(Uri.parse(mGMailInboxUri), null, null, null, null);
c.moveToNext();
int n = c.getColumnIndex(GmailContract.Labels.NUM_UNREAD_CONVERSATIONS);
@ -435,24 +462,24 @@ public class DynamicText extends Shortcut {
new_text = " ";
}
} else {
if(mCursor != null) {
mCursor.requery();
mCursor.moveToFirst();
if (mCursor != null) {
mCursor.requery();
mCursor.moveToFirst();
mCount = mCursor.getCount();
new_text = mCountFormat.format(mCount);
} else {
new_text = " ";
}
}
}
updateVisibility();
break;
case BATTERY_LEVEL:
new_text = mBatteryLevel==-1 ? "" : mCountFormat.format(mBatteryLevel);
new_text = mBatteryLevel == -1 ? "" : mCountFormat.format(mBatteryLevel);
break;
}
if(new_text != null) {
if(!new_text.equals(getLabel())) {
if (new_text != null) {
if (!new_text.equals(getLabel())) {
// TODO propagate changes to views
setLabel(new_text);
}
@ -462,4 +489,6 @@ public class DynamicText extends Shortcut {
private void updateVisibility() {
setVisible(mCount != 0 || mDynamicTextConfig.displayEmpty || mEditMode);
}
}

View file

@ -18,14 +18,6 @@ public class EventAction {
public String data;
public EventAction next;
public static EventAction UNSET() {
return new EventAction(GlobalConfig.UNSET, null);
}
public static final EventAction NOTHING() {
return new EventAction(GlobalConfig.NOTHING, null);
}
public EventAction() {
// empty constructor for serialization
}
@ -41,22 +33,30 @@ public class EventAction {
this.next = next;
}
public static EventAction UNSET() {
return new EventAction(GlobalConfig.UNSET, null);
}
public static final EventAction NOTHING() {
return new EventAction(GlobalConfig.NOTHING, null);
}
public EventAction clone() {
return new EventAction(action, data, next==null ? null : next.clone());
return new EventAction(action, data, next == null ? null : next.clone());
}
public boolean equals(Object o) {
if(o == null) return false;
if(o.getClass() != EventAction.class) return false;
EventAction ea = (EventAction)o;
if(this.action != ea.action) return false;
if((this.data == null && ea.data != null) || (this.data != null && !this.data.equals(ea.data))) return false;
if((this.next == null && ea.next != null) || (this.next != null && !this.next.equals(ea.next))) return false;
return true;
if (o == null) return false;
if (o.getClass() != EventAction.class) return false;
EventAction ea = (EventAction) o;
if (this.action != ea.action) return false;
if ((this.data == null && ea.data != null) || (this.data != null && !this.data.equals(ea.data)))
return false;
return (this.next != null || ea.next == null) && (this.next == null || this.next.equals(ea.next));
}
public String describe(LightningEngine engine) {
if(data != null) {
if (data != null) {
switch (action) {
case GlobalConfig.RUN_SCRIPT:
Pair<Integer, String> idData = Script.decodeIdAndData(data);
@ -88,14 +88,14 @@ public class EventAction {
int p = intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, Page.FIRST_DASHBOARD_PAGE);
Page page = engine.getOrLoadPage(p);
String description = Utils.formatPageName(page, page.findFirstOpener());
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
if (intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
float x = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_X, 0);
float y = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0);
float s = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_SCALE, 1);
boolean absolute = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, true);
DecimalFormat df = new DecimalFormat("0.##");
description += absolute ? " @" : " +";
description += df.format(x)+"x"+df.format(y)+"/"+df.format(s);
description += df.format(x) + "x" + df.format(y) + "/" + df.format(s);
}
return description;
} catch (URISyntaxException e) {
@ -115,7 +115,7 @@ public class EventAction {
case GlobalConfig.SET_VARIABLE:
Variable v = Variable.decode(data);
if(v != null) {
if (v != null) {
return v.describe();
}
break;

View file

@ -17,10 +17,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class FileUtils {
public static final String WALLPAPER_DIR = "wp";
public static final String SYSTEM_WALLPAPER_BITMAP_FILE = "system.png";
public static final String WALLPAPER_DIR = "wp";
public static final String SYSTEM_WALLPAPER_BITMAP_FILE = "system.png";
public static final String SUFFIX_ICON_BACK = "b";
public static final String SUFFIX_ICON_OVER = "o";
@ -31,7 +32,7 @@ public class FileUtils {
public static final String SUFFIX_BOX_BG_FOLDER = "r";
public static final String SUFFIX_APP_DRAWER_AB_BACKGROUND = "a";
public static final String[] ALL_SUFFIXES = new String[] {
public static final String[] ALL_SUFFIXES = new String[]{
FileUtils.SUFFIX_ICON_BACK,
FileUtils.SUFFIX_ICON_OVER,
FileUtils.SUFFIX_ICON_MASK,
@ -42,98 +43,104 @@ public class FileUtils {
FileUtils.SUFFIX_APP_DRAWER_AB_BACKGROUND
};
public static final File LL_EXT_DIR =new File(Environment.getExternalStorageDirectory(), "LightningLauncher");
public static final File LL_TMP_DIR =new File(LL_EXT_DIR, "tmp");
public static final File LL_EXT_DIR = new File(Environment.getExternalStorageDirectory(), "LightningLauncher");
public static final File LL_TMP_DIR = new File(LL_EXT_DIR, "tmp");
public static final File LL_EXT_SCRIPT_DIR = new File(LL_EXT_DIR, "script");
public static final String THEMES_DIR = "LightningLauncher/themes";
private static final byte[] copy_buffer = new byte[4096];
public static void copyStream(InputStream from, OutputStream to) throws IOException {
int n;
while ((n = from.read(copy_buffer)) != -1) {
to.write(copy_buffer, 0, n);
}
}
private static byte[] copy_buffer=new byte[4096];
public static void copyStream(InputStream from, OutputStream to) throws IOException {
int n;
while((n=from.read(copy_buffer))!=-1) {
to.write(copy_buffer, 0, n);
}
}
public static void saveStringToFile(String what, File out) throws IOException {
FileOutputStream fos = null;
try {
out.getParentFile().mkdirs();
fos = new FileOutputStream(out);
fos.write(what.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
out.delete();
throw e;
} finally {
if (fos != null) try {
fos.close();
} catch (Exception e) { /*pass*/ }
}
}
public static void saveStringToFile(String what, File out) throws IOException {
FileOutputStream fos=null;
try {
out.getParentFile().mkdirs();
fos=new FileOutputStream(out);
fos.write(what.getBytes("utf-8"));
} catch(IOException e) {
out.delete();
throw e;
} finally {
if(fos!=null) try { fos.close(); } catch(Exception e) { /*pass*/ }
}
}
public static JSONObject readJSONObjectFromFile(File json_file) {
try {
long t1 = BuildConfig.IS_BETA ? SystemClock.uptimeMillis() : 0;
JSONObject jsonObject = new JSONObject(FileUtils.readFileContent(json_file));
if (BuildConfig.IS_BETA) {
Log.i("LL", "readJSONObjectFromFile in " + (SystemClock.uptimeMillis() - t1) + "ms, length=" + json_file.length() + ", file=" + json_file);
}
return jsonObject;
} catch (Exception e) {
return null;
}
}
public static JSONObject readJSONObjectFromFile(File json_file) {
try {
long t1 = BuildConfig.IS_BETA ? SystemClock.uptimeMillis() : 0;
JSONObject jsonObject = new JSONObject(FileUtils.readFileContent(json_file));
if(BuildConfig.IS_BETA) {
Log.i("LL", "readJSONObjectFromFile in "+(SystemClock.uptimeMillis()-t1)+"ms, length="+json_file.length()+", file="+json_file);
}
return jsonObject;
} catch(Exception e) {
return null;
}
}
public static String readFileContent(File f) {
FileInputStream fis=null;
try {
fis=new FileInputStream(f);
int file_length=(int)f.length();
byte[] data=new byte[file_length];
fis.read(data, 0, file_length);
return new String(data, "utf-8");
} catch(Exception e) {
return null;
} finally {
if(fis!=null) try { fis.close(); } catch(Exception e) {}
}
}
public static String readFileContent(File f) {
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
int file_length = (int) f.length();
byte[] data = new byte[file_length];
fis.read(data, 0, file_length);
return new String(data, StandardCharsets.UTF_8);
} catch (Exception e) {
return null;
} finally {
if (fis != null) try {
fis.close();
} catch (Exception e) {
}
}
}
public static String readInputStreamContent(InputStream is) {
try {
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int n;
while((n=is.read(buffer))>0) {
while ((n = is.read(buffer)) > 0) {
baos.write(buffer, 0, n);
}
return baos.toString("utf8");
} catch(Exception e) {
} catch (Exception e) {
return null;
} finally {
if(is!=null) try { is.close(); } catch(Exception e) {}
if (is != null) try {
is.close();
} catch (Exception e) {
}
}
}
public static final String THEMES_DIR = "LightningLauncher/themes";
public static final File getExternalThemeDir(String theme_id) {
return new File(Environment.getExternalStorageDirectory(), FileUtils.THEMES_DIR+"/"+theme_id);
}
public static File getGlobalConfigFile(File base_dir) {
return new File(base_dir, "config");
}
public static File getSystemConfigFile(Context context) {
return new File(context.getFilesDir(), "system");
}
public static File getCachedDrawablesDir(Context context) {
return new File(context.getCacheDir(), "drawables");
}
public static final File getExternalThemeDir(String theme_id) {
return new File(Environment.getExternalStorageDirectory(), FileUtils.THEMES_DIR + "/" + theme_id);
}
public static File getManifestFile(File base_dir) {
return new File(base_dir, "manifest");
}
public static File getGlobalConfigFile(File base_dir) {
return new File(base_dir, "config");
}
public static File getSystemConfigFile(Context context) {
return new File(context.getFilesDir(), "system");
}
public static File getCachedDrawablesDir(Context context) {
return new File(context.getCacheDir(), "drawables");
}
public static File getManifestFile(File base_dir) {
return new File(base_dir, "manifest");
}
public static File getStateFile(File base_dir) {
return new File(base_dir, "state");
@ -155,53 +162,53 @@ public class FileUtils {
return new File(base_dir, "themes");
}
public static File getPagesDir(File base_dir) {
return new File(base_dir, "pages");
}
public static File getFontsDir(File base_dir) {
return new File(base_dir, API.DIR_FONTS);
}
public static File getPagesDir(File base_dir) {
return new File(base_dir, "pages");
}
public static File getFontsDir(File base_dir) {
return new File(base_dir, API.DIR_FONTS);
}
// can be applied to copy page icon files
public static void copyIcons(byte[] buffer, File from_dir, String from_id, File to_dir, String to_id) {
if (buffer == null) {
buffer = new byte[512];
}
// can be applied to copy page icon files
public static void copyIcons(byte[] buffer, File from_dir, String from_id, File to_dir, String to_id) {
if(buffer == null) {
buffer = new byte[512];
}
for (String code : FileUtils.ALL_SUFFIXES) {
File icon_from = new File(from_dir, from_id + code);
File icon_to = new File(to_dir, to_id + code);
if (icon_from.exists()) {
Utils.copyFileSafe(buffer, icon_from, icon_to);
File icon_from = new File(from_dir, from_id + code);
File icon_to = new File(to_dir, to_id + code);
if (icon_from.exists()) {
Utils.copyFileSafe(buffer, icon_from, icon_to);
} else {
icon_to.delete();
icon_to.delete();
}
}
}
}
}
// an extended version of copyIcons for items, which will copy default and custom icons too
public static void copyItemFiles(int from_id, File from_icon_dir, int to_id, File to_icon_dir) {
byte[] buffer=new byte[4096];
FileUtils.copyIcons(buffer, from_icon_dir, String.valueOf(from_id), to_icon_dir, String.valueOf(to_id));
// an extended version of copyIcons for items, which will copy default and custom icons too
public static void copyItemFiles(int from_id, File from_icon_dir, int to_id, File to_icon_dir) {
byte[] buffer = new byte[4096];
FileUtils.copyIcons(buffer, from_icon_dir, String.valueOf(from_id), to_icon_dir, String.valueOf(to_id));
File file_from, file_to;
file_from=Item.getDefaultIconFile(from_icon_dir, from_id);
file_to = Item.getDefaultIconFile(to_icon_dir, to_id);
if(file_from.exists()) {
Utils.copyFileSafe(buffer, file_from, file_to);
} else {
file_to.delete();
}
File file_from, file_to;
file_from = Item.getDefaultIconFile(from_icon_dir, from_id);
file_to = Item.getDefaultIconFile(to_icon_dir, to_id);
if (file_from.exists()) {
Utils.copyFileSafe(buffer, file_from, file_to);
} else {
file_to.delete();
}
file_from=Item.getCustomIconFile(from_icon_dir, from_id);
file_to=Item.getCustomIconFile(to_icon_dir, to_id);
if(file_from.exists()) {
Utils.copyFileSafe(buffer, file_from, file_to);
} else {
file_to.delete();
}
}
file_from = Item.getCustomIconFile(from_icon_dir, from_id);
file_to = Item.getCustomIconFile(to_icon_dir, to_id);
if (file_from.exists()) {
Utils.copyFileSafe(buffer, file_from, file_to);
} else {
file_to.delete();
}
}
// public static File getGlobalConfigFile(Context context) {
// return getGlobalConfigFile(getAppBaseDir(context));

View file

@ -27,10 +27,6 @@ import java.util.HashMap;
public class IconPack {
public interface IconPackListener {
void onPackApplied(boolean success);
}
public static boolean applyIconPackSync(final Context context, final String package_name, final Page page, final int item_id) {
boolean result = doApplyIconPackInBackground(context, package_name, page, item_id);
doApplyIconPackPostExecute(page, item_id);
@ -53,7 +49,7 @@ public class IconPack {
@Override
protected void onPostExecute(Boolean result) {
doApplyIconPackPostExecute(page, item_id);
if(listener != null) {
if (listener != null) {
listener.onPackApplied(result);
}
@ -70,9 +66,9 @@ public class IconPack {
page.config.defaultShortcutConfig.iconEffectScale = 1;
for(Item i : page.items) {
if(i.getClass() == Shortcut.class) {
Shortcut s = (Shortcut)i;
for (Item i : page.items) {
if (i.getClass() == Shortcut.class) {
Shortcut s = (Shortcut) i;
s.deleteCustomIconFiles(icon_dir);
s.getShortcutConfig().iconEffectScale = 1;
}
@ -96,13 +92,14 @@ public class IconPack {
// build the cache of icon name -> drawable id (legacy way)
HashMap<String, Integer> icon_name_ids = new HashMap<String, Integer>();
if(icon_pack_res_id != 0) {
if (icon_pack_res_id != 0) {
String[] icon_names = res.getStringArray(icon_pack_res_id);
for(String icon_name : icon_names) {
try {
for (String icon_name : icon_names) {
try {
int drawable_res_id = res.getIdentifier(icon_name, "drawable", package_name);
if(drawable_res_id != 0) icon_name_ids.put(icon_name, Integer.valueOf(drawable_res_id));
} catch(Resources.NotFoundException e) {
if (drawable_res_id != 0)
icon_name_ids.put(icon_name, Integer.valueOf(drawable_res_id));
} catch (Resources.NotFoundException e) {
// pass, error in input array
}
}
@ -111,13 +108,13 @@ public class IconPack {
// build the cache of componentname -> drawable id and load icon layers if available
HashMap<String, Integer> component_name_ids = new HashMap<String, Integer>();
ArrayList<Bitmap> icon_effect_back = new ArrayList<Bitmap>();
Bitmap icon_effect_over=null, icon_effect_mask=null;
Bitmap icon_effect_over = null, icon_effect_mask = null;
float icon_effect_scale = 1;
InputStream appfilter_is = null;
try {
XmlPullParser parser;
int appfilter_id = icon_pack.getResources().getIdentifier("appfilter", "xml", package_name);
if(appfilter_id != 0) {
if (appfilter_id != 0) {
parser = icon_pack.getResources().getXml(appfilter_id);
} else {
try {
@ -125,12 +122,12 @@ public class IconPack {
parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(appfilter_is, null);
} catch(IOException e) {
} catch (IOException e) {
parser = null;
}
}
if(parser == null) {
if (parser == null) {
return false;
}
@ -140,32 +137,32 @@ public class IconPack {
String name = parser.getName();
if (name.equals("iconback")) {
String n = parser.getAttributeValue(null, "img");
if(n == null) {
for(int i=1; i<30; i++) {
n = parser.getAttributeValue(null, "img"+i);
if(n == null) {
if (n == null) {
for (int i = 1; i < 30; i++) {
n = parser.getAttributeValue(null, "img" + i);
if (n == null) {
break;
}
Bitmap b = loadBitmapFromDrawable(res, package_name, n);
if(b != null) {
if (b != null) {
icon_effect_back.add(b);
}
}
} else {
Bitmap b = loadBitmapFromDrawable(res, package_name, n);
if(b != null) {
if (b != null) {
icon_effect_back.add(b);
}
}
} else if (name.equals("iconupon")) {
String n = parser.getAttributeValue(null, "img");
if(n == null) {
if (n == null) {
n = parser.getAttributeValue(null, "img1");
}
icon_effect_over = loadBitmapFromDrawable(res, package_name, n);
} else if (name.equals("iconmask")) {
String n = parser.getAttributeValue(null, "img");
if(n == null) {
if (n == null) {
n = parser.getAttributeValue(null, "img1");
}
icon_effect_mask = loadBitmapFromDrawable(res, package_name, n);
@ -174,16 +171,17 @@ public class IconPack {
} else if (name.equals("item")) {
String component = parser.getAttributeValue(null, "component");
String drawable = parser.getAttributeValue(null, "drawable");
try {
String component_name = component.substring(component.indexOf('{')+1, component.indexOf('}'));
if(component_name.indexOf('/') == -1) {
component_name = component_name.substring(0, component_name.lastIndexOf('.')-1) + "/" + component_name;
try {
String component_name = component.substring(component.indexOf('{') + 1, component.indexOf('}'));
if (component_name.indexOf('/') == -1) {
component_name = component_name.substring(0, component_name.lastIndexOf('.') - 1) + "/" + component_name;
}
ComponentName cn = ComponentName.unflattenFromString(component_name);
int drawable_res_id = res.getIdentifier(drawable, "drawable", package_name);
if(drawable_res_id != 0) component_name_ids.put(cn.flattenToString(), Integer.valueOf(drawable_res_id));
} catch(Exception e) {
if (drawable_res_id != 0)
component_name_ids.put(cn.flattenToString(), Integer.valueOf(drawable_res_id));
} catch (Exception e) {
Log.i("LL", "unable to decode " + component);
// pass, error in input array
}
@ -194,7 +192,10 @@ public class IconPack {
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if(appfilter_is != null) try { appfilter_is.close(); } catch (IOException e) {}
if (appfilter_is != null) try {
appfilter_is.close();
} catch (IOException e) {
}
}
// File pages_dir = FileUtils.getPagesDir(Customize.this);
@ -227,55 +228,59 @@ public class IconPack {
File icon_dir = page.getAndCreateIconDir();
icon_dir.mkdirs();
if(item_id == Item.NO_ID) {
if (item_id == Item.NO_ID) {
File icon_effect_back_file = new File(icon_dir, "b");
if (icon_effect_back.size() > 0) saveBitmapToFile(icon_effect_back.get(0), icon_effect_back_file); else icon_effect_back_file.delete();
if (icon_effect_back.size() > 0)
saveBitmapToFile(icon_effect_back.get(0), icon_effect_back_file);
else icon_effect_back_file.delete();
File icon_effect_over_file = new File(icon_dir, "o");
if (icon_effect_over != null) saveBitmapToFile(icon_effect_over, icon_effect_over_file); else icon_effect_over_file.delete();
if (icon_effect_over != null) saveBitmapToFile(icon_effect_over, icon_effect_over_file);
else icon_effect_over_file.delete();
File icon_effect_mask_file = new File(icon_dir, "m");
if (icon_effect_mask != null) saveBitmapToFile(icon_effect_mask, icon_effect_mask_file); else icon_effect_mask_file.delete();
if (icon_effect_mask != null) saveBitmapToFile(icon_effect_mask, icon_effect_mask_file);
else icon_effect_mask_file.delete();
page.setModified();
}
// update items custom icon
int n = 0;
for(Item i : page.items) {
if(item_id != Item.NO_ID && i.mId != item_id) {
for (Item i : page.items) {
if (item_id != Item.NO_ID && i.mId != item_id) {
continue;
}
if(i.getClass() == Shortcut.class) {
Shortcut s = (Shortcut)i;
if (i.getClass() == Shortcut.class) {
Shortcut s = (Shortcut) i;
boolean icon_found = false;
ComponentName cn = s.getIntent().getComponent();
if(cn != null) {
if (cn != null) {
// try to get an id through the appfilter way
Integer drawable_id = component_name_ids.get(cn.flattenToString());
if(drawable_id == null) {
if (drawable_id == null) {
// try to find an id, either with or without the activity name (try with the activty name first, otherwise try only the package)
String class_name = cn.getClassName();
String icon_name = class_name.replace('.', '_').toLowerCase();
drawable_id = icon_name_ids.get(icon_name);
if(drawable_id == null) {
int pos = class_name.lastIndexOf('.')+1; // if not found will produce 0 which is fine
icon_name = (cn.getPackageName()+"_"+class_name.substring(pos)).replace('.', '_').toLowerCase();
if (drawable_id == null) {
int pos = class_name.lastIndexOf('.') + 1; // if not found will produce 0 which is fine
icon_name = (cn.getPackageName() + "_" + class_name.substring(pos)).replace('.', '_').toLowerCase();
drawable_id = icon_name_ids.get(icon_name);
if(drawable_id == null) {
if (drawable_id == null) {
icon_name = cn.getPackageName().replace('.', '_').toLowerCase();
drawable_id = icon_name_ids.get(icon_name);
}
}
}
if(drawable_id != null) {
if (drawable_id != null) {
// save the drawable using the target size (if less than the icon from the pack)
String default_icon_path = icon_dir+"/"+s.getId();
File custom_icon_file = new File(default_icon_path+"c");
String default_icon_path = icon_dir + "/" + s.getId();
File custom_icon_file = new File(default_icon_path + "c");
Drawable drawable = Utils.decodeDrawableResource(res, drawable_id.intValue());
if(drawable != null) {
if (drawable != null) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(default_icon_path, opts);
@ -293,16 +298,16 @@ public class IconPack {
}
}
if(icon_found) {
if (icon_found) {
int id = s.getId();
ShortcutConfig sc = s.getShortcutConfig().clone();
sc.iconEffectScale = 1;
saveEmptyBitmap(sc.getIconBackFile(icon_dir, id));
saveEmptyBitmap(sc.getIconOverFile(icon_dir, id));
saveEmptyBitmap(sc.getIconMaskFile(icon_dir, id));
saveEmptyBitmap(ShortcutConfig.getIconBackFile(icon_dir, id));
saveEmptyBitmap(ShortcutConfig.getIconOverFile(icon_dir, id));
saveEmptyBitmap(ShortcutConfig.getIconMaskFile(icon_dir, id));
s.setShortcutConfig(sc);
} else if(icon_effect_back.size() > 1) {
Bitmap bitmap = icon_effect_back.get((n++)%icon_effect_back.size());
} else if (icon_effect_back.size() > 1) {
Bitmap bitmap = icon_effect_back.get((n++) % icon_effect_back.size());
saveBitmapToFile(bitmap, ShortcutConfig.getIconBackFile(icon_dir, s.getId()));
s.modifyShortcutConfig().iconEffectScale = icon_effect_scale;
}
@ -313,7 +318,7 @@ public class IconPack {
}
private static void doApplyIconPackPostExecute(Page page, int item_id) {
if(item_id == Item.NO_ID) {
if (item_id == Item.NO_ID) {
page.save();
page.reload();
} else {
@ -321,7 +326,6 @@ public class IconPack {
}
}
private static void saveEmptyBitmap(File to) {
FileOutputStream fos = null;
try {
@ -333,7 +337,9 @@ public class IconPack {
} catch (IOException e) {
to.delete();
} finally {
if(fos != null) try { fos.close(); } catch (IOException e) { /*pass*/ }
if (fos != null) try {
fos.close();
} catch (IOException e) { /*pass*/ }
}
}
@ -341,10 +347,10 @@ public class IconPack {
int id = res.getIdentifier(name, "drawable", package_name);
try {
Drawable d = res.getDrawable(id);
if(d instanceof BitmapDrawable) {
return ((BitmapDrawable)d).getBitmap();
if (d instanceof BitmapDrawable) {
return ((BitmapDrawable) d).getBitmap();
}
} catch(Resources.NotFoundException e) {
} catch (Resources.NotFoundException e) {
// pass
}
return null;
@ -355,10 +361,17 @@ public class IconPack {
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch(IOException e) {
} catch (IOException e) {
file.delete();
} finally {
if(fos != null) try { fos.close(); } catch(IOException e) {}
if (fos != null) try {
fos.close();
} catch (IOException e) {
}
}
}
public interface IconPackListener {
void onPackApplied(boolean success);
}
}

View file

@ -16,79 +16,83 @@ import java.lang.reflect.Modifier;
import java.util.HashMap;
public class JsonLoader {
/** Specialized for configuration objects, not a multi-purpose tool. */
public static JSONObject toJSONObject(Object o, Object default_value) {
JSONObject json_object=new JSONObject();
/**
* Specialized for configuration objects, not a multi-purpose tool.
*/
public static JSONObject toJSONObject(Object o, Object default_value) {
JSONObject json_object = new JSONObject();
toJSONObject(json_object, o, default_value);
return json_object;
}
/** Specialized for configuration objects, not a multi-purpose tool. */
public static void toJSONObject(JSONObject json_object, Object o, Object default_value) {
for(Field f : o.getClass().getFields()) {
if(Modifier.isFinal(f.getModifiers())) continue;
/**
* Specialized for configuration objects, not a multi-purpose tool.
*/
public static void toJSONObject(JSONObject json_object, Object o, Object default_value) {
for (Field f : o.getClass().getFields()) {
if (Modifier.isFinal(f.getModifiers())) continue;
if(default_value!=null) {
try {
Object f_o = f.get(o);
Object f_do = f.get(default_value);
if(f_o==null && f_do==null) continue;
if(f_o!=null && f_o.equals(f_do)) continue;
} catch (Exception e1) {
e1.printStackTrace();
}
}
if (default_value != null) {
try {
Object f_o = f.get(o);
Object f_do = f.get(default_value);
if (f_o == null && f_do == null) continue;
if (f_o != null && f_o.equals(f_do)) continue;
} catch (Exception e1) {
e1.printStackTrace();
}
}
String name=f.getName();
String name = f.getName();
try {
Class<?> cls=f.getType();
if(cls==boolean.class) {
json_object.put(name, f.getBoolean(o));
} else if(cls==int.class) {
json_object.put(name, f.getInt(o));
} else if(cls==long.class) {
try {
Class<?> cls = f.getType();
if (cls == boolean.class) {
json_object.put(name, f.getBoolean(o));
} else if (cls == int.class) {
json_object.put(name, f.getInt(o));
} else if (cls == long.class) {
json_object.put(name, f.getLong(o));
} else if(cls==int[].class) {
int[] ai=(int[])f.get(o);
if(ai!=null) {
JSONArray jai=new JSONArray();
for(int i : ai) {
jai.put(i);
}
json_object.put(name, jai);
}
} else if(cls==float.class) {
json_object.put(name, (double)f.getFloat(o));
} else if(cls==String.class) {
json_object.put(name, (String)f.get(o));
} else if(cls==String[].class) {
String[] as=(String[])f.get(o);
if(as!=null) {
JSONArray jas=new JSONArray();
for(String s : as) {
} else if (cls == int[].class) {
int[] ai = (int[]) f.get(o);
if (ai != null) {
JSONArray jai = new JSONArray();
for (int i : ai) {
jai.put(i);
}
json_object.put(name, jai);
}
} else if (cls == float.class) {
json_object.put(name, f.getFloat(o));
} else if (cls == String.class) {
json_object.put(name, f.get(o));
} else if (cls == String[].class) {
String[] as = (String[]) f.get(o);
if (as != null) {
JSONArray jas = new JSONArray();
for (String s : as) {
jas.put(s);
}
json_object.put(name, jas);
}
} else if(cls==EventAction.class) {
} else if (cls == EventAction.class) {
EventAction ea = (EventAction) f.get(o);
if (ea != null && ea.action != GlobalConfig.UNSET) {
JSONObject j_ea = new JSONObject();
j_ea.put("a", ea.action);
j_ea.put("d", ea.data);
if(ea.next != null) {
if (ea.next != null) {
j_ea.put("n", toJSONObject(ea.next, null));
}
json_object.put(name, j_ea);
}
} else if(cls== Binding[].class) {
Binding[] bindings=(Binding[])f.get(o);
if(bindings!=null) {
JSONArray jbindings=new JSONArray();
for(Binding binding : bindings) {
} else if (cls == Binding[].class) {
Binding[] bindings = (Binding[]) f.get(o);
if (bindings != null) {
JSONArray jbindings = new JSONArray();
for (Binding binding : bindings) {
JSONObject j = new JSONObject();
j.put("t", binding.target);
j.put("f", binding.formula);
@ -97,86 +101,82 @@ public class JsonLoader {
}
json_object.put(name, jbindings);
}
} else if(cls==HashMap.class) {
} else if (cls == HashMap.class) {
HashMap m = (HashMap) f.get(o);
if(m != null) {
json_object.put(name, new JSONObject((HashMap)f.get(o)));
if (m != null) {
json_object.put(name, new JSONObject((HashMap) f.get(o)));
}
} else if(cls.isEnum()) {
} else if (cls.isEnum()) {
json_object.put(name, f.get(o).toString());
}
} catch(IllegalAccessException e) {
e.printStackTrace();
} catch (JSONException e) {
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void loadFieldsFromJSONObject(JSONObject json, Object d) {
loadFieldsFromJSONObject(this, json, d);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void loadFieldsFromJSONObject(Object thiz, JSONObject json, Object d) {
if(d == null) {
@SuppressWarnings({"rawtypes", "unchecked"})
public static void loadFieldsFromJSONObject(Object thiz, JSONObject json, Object d) {
if (d == null) {
d = thiz;
}
for(Field f : thiz.getClass().getFields()) {
if(Modifier.isFinal(f.getModifiers())) continue;
String name=f.getName();
try {
Class<?> cls=f.getType();
if(cls==boolean.class) {
f.setBoolean(thiz, json.optBoolean(name, f.getBoolean(d)));
} else if(cls==int.class) {
f.setInt(thiz, json.optInt(name, f.getInt(d)));
} else if(cls==int[].class) {
JSONArray a = json.optJSONArray(name);
if(a==null) {
f.set(thiz, null);
} else {
int n=a.length();
int[] ai=new int[n];
for(int i=0; i<n; i++) {
ai[i] = a.getInt(i);
}
f.set(thiz, ai);
}
} else if(cls==float.class) {
f.setFloat(thiz, (float)json.optDouble(name, f.getDouble(d)));
} else if(cls==long.class) {
f.setLong(thiz, json.optLong(name, f.getLong(d)));
} else if(cls==String.class) {
f.set(thiz, json.optString(name, (String)f.get(d)));
} else if(cls==String[].class) {
for (Field f : thiz.getClass().getFields()) {
if (Modifier.isFinal(f.getModifiers())) continue;
String name = f.getName();
try {
Class<?> cls = f.getType();
if (cls == boolean.class) {
f.setBoolean(thiz, json.optBoolean(name, f.getBoolean(d)));
} else if (cls == int.class) {
f.setInt(thiz, json.optInt(name, f.getInt(d)));
} else if (cls == int[].class) {
JSONArray a = json.optJSONArray(name);
if(a==null) {
if (a == null) {
f.set(thiz, null);
} else {
int n=a.length();
String[] as=new String[n];
for(int i=0; i<n; i++) {
int n = a.length();
int[] ai = new int[n];
for (int i = 0; i < n; i++) {
ai[i] = a.getInt(i);
}
f.set(thiz, ai);
}
} else if (cls == float.class) {
f.setFloat(thiz, (float) json.optDouble(name, f.getDouble(d)));
} else if (cls == long.class) {
f.setLong(thiz, json.optLong(name, f.getLong(d)));
} else if (cls == String.class) {
f.set(thiz, json.optString(name, (String) f.get(d)));
} else if (cls == String[].class) {
JSONArray a = json.optJSONArray(name);
if (a == null) {
f.set(thiz, null);
} else {
int n = a.length();
String[] as = new String[n];
for (int i = 0; i < n; i++) {
as[i] = a.getString(i);
}
f.set(thiz, as);
}
} else if(cls.isEnum()) {
String enum_string=json.optString(name, null);
if(enum_string!=null) {
f.set(thiz, Enum.valueOf((Class<Enum>)cls, enum_string));
} else {
f.set(thiz, f.get(d));
}
} else if(cls==EventAction.class) {
} else if (cls.isEnum()) {
String enum_string = json.optString(name, null);
if (enum_string != null) {
f.set(thiz, Enum.valueOf((Class<Enum>) cls, enum_string));
} else {
f.set(thiz, f.get(d));
}
} else if (cls == EventAction.class) {
EventAction ea;
if (json.has(name)) {
try {
JSONObject j_ea = json.getJSONObject(name);
JSONObject n = j_ea.optJSONObject("n");
EventAction next = null;
if(n != null) {
if (n != null) {
next = new EventAction();
loadFieldsFromJSONObject(next, n, null);
}
@ -191,14 +191,14 @@ public class JsonLoader {
ea = d_ea;
}
f.set(thiz, ea);
} else if(cls== Binding[].class) {
} else if (cls == Binding[].class) {
JSONArray a = json.optJSONArray(name);
if(a==null) {
if (a == null) {
f.set(thiz, null);
} else {
int n=a.length();
int n = a.length();
Binding[] bindings;
if(n==0) {
if (n == 0) {
bindings = null;
} else {
bindings = new Binding[n];
@ -210,37 +210,29 @@ public class JsonLoader {
}
f.set(thiz, bindings);
}
} else if(cls==HashMap.class) {
} else if (cls == HashMap.class) {
JSONObject o = json.optJSONObject(name);
if(o != null) {
if (o != null) {
f.set(thiz, Utils.jsonObjectToHashMap(o));
} else {
f.set(thiz, f.get(d));
}
} else if(cls.getSuperclass()==JsonLoader.class) {
JsonLoader j=(JsonLoader)cls.newInstance();
JSONObject o2=json.optJSONObject(name);
if(o2==null) {
o2=new JSONObject();
}
j.loadFieldsFromJSONObject(o2, f.get(d));
f.set(thiz, j);
} else if (cls.getSuperclass() == JsonLoader.class) {
JsonLoader j = (JsonLoader) cls.newInstance();
JSONObject o2 = json.optJSONObject(name);
if (o2 == null) {
o2 = new JSONObject();
}
j.loadFieldsFromJSONObject(o2, f.get(d));
f.set(thiz, j);
}
} catch(Exception e) {
Log.i("LL", "bad field "+name);
// pass
} catch (Exception e) {
Log.i("LL", "bad field " + name);
// pass
// e.printStackTrace();
}
}
}
public void copyFrom(JsonLoader o) {
try {
loadFieldsFromJSONObject(toJSONObject(o, null), o);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public static <T extends JsonLoader> T readObject(Class<T> cls, File from) {
T instance;
@ -252,7 +244,7 @@ public class JsonLoader {
}
JSONObject json = FileUtils.readJSONObjectFromFile(from);
if(json != null) {
if (json != null) {
instance.loadFieldsFromJSONObject(json, instance);
}
@ -270,6 +262,18 @@ public class JsonLoader {
}
}
public void loadFieldsFromJSONObject(JSONObject json, Object d) {
loadFieldsFromJSONObject(this, json, d);
}
public void copyFrom(JsonLoader o) {
try {
loadFieldsFromJSONObject(toJSONObject(o, null), o);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return JsonLoader.toJSONObject(this, null).toString();

View file

@ -3,12 +3,18 @@ package net.pierrox.lightning_launcher.data;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.os.SystemClock;
import android.util.Log;
import net.pierrox.lightning_launcher.configuration.*;
import net.pierrox.lightning_launcher.BuildConfig;
import net.pierrox.lightning_launcher.configuration.FolderConfig;
import net.pierrox.lightning_launcher.configuration.FolderConfigStylable;
import net.pierrox.lightning_launcher.configuration.ItemConfig;
import net.pierrox.lightning_launcher.configuration.ItemConfigStylable;
import net.pierrox.lightning_launcher.configuration.JsonFields;
import net.pierrox.lightning_launcher.configuration.PageConfig;
import net.pierrox.lightning_launcher.configuration.ShortcutConfig;
import net.pierrox.lightning_launcher.configuration.ShortcutConfigStylable;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.views.ItemLayout;
import net.pierrox.lightning_launcher.views.item.ItemView;
@ -28,82 +34,43 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
// home pages: 0->98, app app_drawer:99, folders: 100->N
// these ids are stored as string, even if only numeric values today
public static final int NONE =-1;
public static final int FIRST_DASHBOARD_PAGE=0;
public static final int LAST_DASHBOARD_PAGE=98;
public static final int APP_DRAWER_PAGE=99;
public static final int FIRST_FOLDER_PAGE=100;
public static final int LAST_FOLDER_PAGE=999;
public static final int USER_MENU_PAGE=0x7fff;
public static final int MERGED_APP_DRAWER_PAGE=0x7ffe;
public interface PageListener extends Item.OnItemEventListener{
public void onPageLoaded(Page page);
public void onPageRemoved(Page page);
public void onPagePaused(Page page);
public void onPageResumed(Page page);
public void onPageModified(Page page);
// TODO move this to engine, this is not a page specific data
public void onPageEditModeEntered(Page page);
public void onPageEditModeLeaved(Page page);
public void onPageItemLoaded(Item item);
public void onPageItemDestroyed(Item item);
public void onPageItemAdded(Item item);
public void onPageItemBeforeRemove(Item item);
public void onPageItemRemoved(Page page, Item item);
public void onPageItemChanged(Page page, Item item);
public void onPageItemZIndexChanged(Page page, int old_index, int new_index);
public void onPageFolderWindowChanged(Page page, Folder folder);
}
public static class EmptyPageListener implements PageListener {
@Override public void onPageLoaded(Page page) { }
@Override public void onPageRemoved(Page page) { }
@Override public void onPagePaused(Page page) { }
@Override public void onPageResumed(Page page) { }
@Override public void onPageModified(Page page) { }
@Override public void onPageEditModeEntered(Page page) { }
@Override public void onPageEditModeLeaved(Page page) { }
@Override public void onPageItemLoaded(Item item) { }
@Override public void onPageItemDestroyed(Item item) { }
@Override public void onPageItemAdded(Item item) { }
@Override public void onPageItemBeforeRemove(Item item) { }
@Override public void onPageItemRemoved(Page page, Item item) { }
@Override public void onPageItemChanged(Page page, Item item) { }
@Override public void onPageItemZIndexChanged(Page page, int old_index, int new_index) { }
@Override public void onPageFolderWindowChanged(Page page, Folder folder) { }
@Override public void onItemPaused(Item item) { }
@Override public void onItemResumed(Item item) { }
@Override public void onItemVisibilityChanged(Item item) { }
@Override public void onItemAlphaChanged(Item item) { }
@Override public void onItemTransformChanged(Item item, boolean fast) { }
@Override public void onItemCellChanged(Item item) { }
@Override public void onItemBindingsChanged(Item item, boolean apply) { }
@Override public void onItemError(Item item, Error error) { }
@Override public void onShortcutLabelChanged(Shortcut shortcut) { }
@Override public void onFolderPageIdChanged(Folder folder, int oldPageId) { }
}
public static final int NONE = -1;
public static final int FIRST_DASHBOARD_PAGE = 0;
public static final int LAST_DASHBOARD_PAGE = 98;
public static final int APP_DRAWER_PAGE = 99;
public static final int FIRST_FOLDER_PAGE = 100;
public static final int LAST_FOLDER_PAGE = 999;
public static final int USER_MENU_PAGE = 0x7fff;
public static final int MERGED_APP_DRAWER_PAGE = 0x7ffe;
private static final String _backgroundColor = "backgroundColor";
private static final String _backgroundWallpaper = "backgroundWallpaper";
private static final String _backgroundWallpaperScroll = "backgroundWallpaperScroll";
private static final String _backgroundWallpaperTintColor = "backgroundWallpaperTintColor";
private static final String _backgroundWallpaperWidth = "backgroundWallpaperWidth";
private static final String _backgroundWallpaperHeight = "backgroundWallpaperHeight";
private static final String _gridColumnMode = "gridColumnMode";
private static final String _gridColumnNum = "gridColumnNum";
private static final String _gridColumnSize = "gridColumnSize";
private static final String _gridRowMode = "gridRowMode";
private static final String _gridRowNum = "gridRowNum";
private static final String _gridRowSize = "gridRowSize";
private static final String _layoutMode = "layoutMode";
private static final String _transpBarOverlap = "transpBarOverlap";
private static final String _statusBarTransparent = "statusBarTransparent";
private static final String _navigationBarTransparent = "navigationBarTransparent";
private static final String _wrap = "wrap";
private final File mIconDir;
public int id;
public PageConfig config;
public ArrayList<Item> items;
protected PageListener mListener;
// TODO both fields are the same
private LightningEngine mLightningEngine;
protected PageListener mListener;
private File mIconDir;
private boolean modified;
public int id;
public PageConfig config;
public ArrayList<Item> items;
private boolean modified;
private float mCurrentViewCellWidth;
private float mCurrentViewCellHeight;
private int mResumeCount;
private boolean mIsBeingRemoved; // prevent endless recursion
public Page(LightningEngine lightningEngine, int id) {
mLightningEngine = lightningEngine;
@ -112,42 +79,110 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
mIconDir = getIconDir(mLightningEngine.getBaseDir(), id);
}
@Override
public String toString() {
return "Page:"+id+" ("+hashCode()+")";
public static boolean isDashboard(int p) {
return p >= FIRST_DASHBOARD_PAGE && p <= LAST_DASHBOARD_PAGE;
}
public static boolean isDashboard(int p) {
return p>=FIRST_DASHBOARD_PAGE && p<=LAST_DASHBOARD_PAGE;
public static boolean isFolder(int p) {
return (p >= FIRST_FOLDER_PAGE && p <= LAST_FOLDER_PAGE) || p == USER_MENU_PAGE;
}
public static int composeItemId(int page, int item_id) {
return page << 16 | (item_id & 0xffff);
}
public static int getBaseItemId(int item_id) {
return item_id & 0xffff;
}
public static boolean exists(File base_dir, int id) {
return getPageDir(base_dir, id).exists();
}
// static versions
// TODO: remove when possible
public static File getPageDir(File base_dir, int id) {
return new File(FileUtils.getPagesDir(base_dir), String.valueOf(id));
}
public static File getIconDir(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "icon");
}
public static File getAndCreateIconDir(File base_dir, int id) {
File icon_dir = getIconDir(base_dir, id);
if (!icon_dir.exists()) {
icon_dir.mkdirs();
}
return icon_dir;
}
// TODO: remove when possible, or move to PageManager
public static File getItemsFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "items");
}
public static File getPageIconFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "i");
}
public static File getWallpaperFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "wp");
}
public static File getPageConfigFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "conf");
}
// TODO: move this into PageManager
public static int reservePage(File base_dir, boolean folder) {
int start, end;
if (folder) {
start = FIRST_FOLDER_PAGE;
end = LAST_FOLDER_PAGE;
} else {
start = FIRST_DASHBOARD_PAGE;
end = LAST_DASHBOARD_PAGE;
}
for (int i = start; i <= end; i++) {
File page_dir = getPageDir(base_dir, i);
if (!page_dir.exists()) {
page_dir.mkdirs();
return i;
}
}
return NONE;
}
@Override
public String toString() {
return "Page:" + id + " (" + hashCode() + ")";
}
public boolean isDashboard() {
return isDashboard(id);
}
public static boolean isFolder(int p) {
return (p>=FIRST_FOLDER_PAGE && p<=LAST_FOLDER_PAGE) || p == USER_MENU_PAGE;
}
public boolean isFolder() {
return isFolder(id);
}
public void setEngine(LightningEngine lightningEngine) {
mLightningEngine = lightningEngine;
}
public LightningEngine getEngine() {
return mLightningEngine;
}
public void setEngine(LightningEngine lightningEngine) {
mLightningEngine = lightningEngine;
}
public void pause() {
mResumeCount--;
// Log.i("XXX", "pause page "+id+" "+mResumeCount);
if(mResumeCount == 0) {
if (mResumeCount == 0) {
// Log.i("XXX", "pause page "+id);
for(Item item : items) {
for (Item item : items) {
item.pause();
}
mListener.onPagePaused(this);
@ -157,7 +192,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void resume() {
mResumeCount++;
// Log.i("XXX", "resume page "+id+" "+mResumeCount);
if(mResumeCount == 1) {
if (mResumeCount == 1) {
// Log.i("XXX", "resume page "+id);
for (Item item : items) {
item.resume();
@ -181,16 +216,16 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
loadConfig();
if(isFolder(id)) {
if (isFolder(id)) {
// use the default folder config from the first home page, which is not perfect but better to have multiple folder config per folder
Page home = mLightningEngine.getOrLoadPage(FIRST_DASHBOARD_PAGE);
config.defaultFolderConfig=home.config.defaultFolderConfig;
config.defaultFolderConfig = home.config.defaultFolderConfig;
}
loadItems();
if(BuildConfig.IS_BETA) {
Log.i("LL", "page "+id+" created in " + (SystemClock.uptimeMillis()-t1)+"ms, "+items.size()+" items, json file size: "+getItemsFile().length()+", config file size: "+getPageConfigFile().length());
if (BuildConfig.IS_BETA) {
Log.i("LL", "page " + id + " created in " + (SystemClock.uptimeMillis() - t1) + "ms, " + items.size() + " items, json file size: " + getItemsFile().length() + ", config file size: " + getPageConfigFile().length());
}
}
@ -200,19 +235,18 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void destroy() {
// Log.i("XXX", "destroy page "+page);
if(mResumeCount > 0) {
if (mResumeCount > 0) {
pause();
mResumeCount = 0;
}
for(Item item : items) {
for (Item item : items) {
mListener.onPageItemDestroyed(item);
item.onDestroy();
}
}
private boolean mIsBeingRemoved; // prevent endless recursion
public void remove() {
if(!mIsBeingRemoved) {
if (!mIsBeingRemoved) {
mIsBeingRemoved = true;
for (Item item : items) {
@ -241,33 +275,25 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
}
public void save() {
if(modified && id != Page.NONE) {
if (modified && id != Page.NONE) {
saveConfig();
saveItems();
modified=false;
modified = false;
}
}
public static int composeItemId(int page, int item_id) {
return page<<16 | (item_id&0xffff);
}
public static int getBaseItemId(int item_id) {
return item_id&0xffff;
}
public int findFreeItemId() {
// linked with Utils.getPageForItemId
int max=0;
for(Item i : items) {
if(i.getId()>max) max=i.getId();
int max = 0;
for (Item i : items) {
if (i.getId() > max) max = i.getId();
}
return composeItemId(id, max+1);
return composeItemId(id, max + 1);
}
public Item findItemById(int id) {
for(Item i : items) {
if(i.getId()==id) return i;
for (Item i : items) {
if (i.getId() == id) return i;
}
return null;
}
@ -295,75 +321,9 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public File getIconDir() {
return mIconDir;
}
public File getAndCreateIconDir() {
return getAndCreateIconDir(mLightningEngine.getBaseDir(), id);
}
public static boolean exists(File base_dir, int id) {
return getPageDir(base_dir, id).exists();
}
// static versions
// TODO: remove when possible
public static File getPageDir(File base_dir, int id) {
return new File(FileUtils.getPagesDir(base_dir), String.valueOf(id));
}
public static File getIconDir(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "icon");
}
public static File getAndCreateIconDir(File base_dir, int id) {
File icon_dir = getIconDir(base_dir, id);
if(!icon_dir.exists()) {
icon_dir.mkdirs();
}
return icon_dir;
}
// TODO: remove when possible, or move to PageManager
public static File getItemsFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "items");
}
public static File getPageIconFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "i");
}
public static File getWallpaperFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "wp");
}
public static File getPageConfigFile(File base_dir, int id) {
return new File(getPageDir(base_dir, id), "conf");
}
// TODO: move this into PageManager
public static int reservePage(File base_dir, boolean folder) {
int start, end;
if(folder) {
start = FIRST_FOLDER_PAGE;
end = LAST_FOLDER_PAGE;
} else {
start = FIRST_DASHBOARD_PAGE;
end = LAST_DASHBOARD_PAGE;
}
for(int i=start; i<=end; i++) {
File page_dir=getPageDir(base_dir, i);
if(!page_dir.exists()) {
page_dir.mkdirs();
return i;
}
}
return NONE;
}
@Override
public void setItemConfig(ItemConfig c) {
config.defaultItemConfig = c;
return getAndCreateIconDir(mLightningEngine.getBaseDir(), id);
}
@Override
@ -371,6 +331,11 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
return config.defaultItemConfig;
}
@Override
public void setItemConfig(ItemConfig c) {
config.defaultItemConfig = c;
}
@Override
public ItemConfig modifyItemConfig() {
return config.defaultItemConfig;
@ -406,7 +371,6 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
return config.defaultFolderConfig;
}
@Override
public void onItemPaused(Item item) {
mListener.onItemPaused(item);
@ -454,7 +418,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
@Override
public void onFolderPageIdChanged(Folder folder, int oldPageId) {
if(items.contains(folder)) {
if (items.contains(folder)) {
mListener.onFolderPageIdChanged(folder, oldPageId);
}
}
@ -466,7 +430,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void setItemZIndex(Item item, int new_index) {
int old_index = items.indexOf(item);
if(old_index != new_index && new_index >=0 && new_index < items.size()) {
if (old_index != new_index && new_index >= 0 && new_index < items.size()) {
items.remove(old_index);
items.add(new_index, item);
@ -481,14 +445,14 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void addItem(Item item, Integer index) {
modified = true;
if(index == null) {
if (index == null) {
items.add(item);
} else {
items.add(index, item);
}
mListener.onPageItemAdded(item);
if(mResumeCount > 0) {
if (mResumeCount > 0) {
item.resume();
}
}
@ -497,13 +461,13 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
mListener.onPageItemBeforeRemove(item);
modified = true;
if(mResumeCount > 0) item.pause();
if (mResumeCount > 0) item.pause();
item.onDestroy();
item.onRemove(keepResources);
items.remove(item);
ArrayList<File> icons = new ArrayList<>();
item.getIconFiles(getIconDir(), icons);
for(File f : icons) {
for (File f : icons) {
f.delete();
}
mListener.onPageItemRemoved(this, item);
@ -520,19 +484,19 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
mListener.onPageItemChanged(this, item);
if(mResumeCount > 0) {
if (mResumeCount > 0) {
item.resume();
}
}
public void notifyItemChanged(Item item) {
modified = true;
if(mResumeCount > 0) item.pause();
if (mResumeCount > 0) item.pause();
item.onDestroy();
item.onCreate();
mListener.onPageItemChanged(this, item);
if(mResumeCount > 0) {
if (mResumeCount > 0) {
item.resume();
}
}
@ -547,66 +511,48 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
}
public float getCurrentViewCellWidth() {
return mCurrentViewCellWidth==0 ? Utils.getStandardIconSize() : mCurrentViewCellWidth;
return mCurrentViewCellWidth == 0 ? Utils.getStandardIconSize() : mCurrentViewCellWidth;
}
public float getCurrentViewCellHeight() {
return mCurrentViewCellHeight==0 ? Utils.getStandardIconSize() : mCurrentViewCellHeight;
return mCurrentViewCellHeight == 0 ? Utils.getStandardIconSize() : mCurrentViewCellHeight;
}
public void reload() {
int count = mResumeCount;
destroy();
create();
if(count > 0) {
destroy();
create();
if (count > 0) {
resume();
mResumeCount = count;
}
notifyModified();
notifyModified();
}
private static final String _backgroundColor = "backgroundColor";
private static final String _backgroundWallpaper = "backgroundWallpaper";
private static final String _backgroundWallpaperScroll = "backgroundWallpaperScroll";
private static final String _backgroundWallpaperTintColor = "backgroundWallpaperTintColor";
private static final String _backgroundWallpaperWidth = "backgroundWallpaperWidth";
private static final String _backgroundWallpaperHeight = "backgroundWallpaperHeight";
private static final String _gridColumnMode = "gridColumnMode";
private static final String _gridColumnNum = "gridColumnNum";
private static final String _gridColumnSize = "gridColumnSize";
private static final String _gridRowMode = "gridRowMode";
private static final String _gridRowNum = "gridRowNum";
private static final String _gridRowSize = "gridRowSize";
private static final String _layoutMode = "layoutMode";
private static final String _transpBarOverlap = "transpBarOverlap";
private static final String _statusBarTransparent = "statusBarTransparent";
private static final String _navigationBarTransparent = "navigationBarTransparent";
private static final String _wrap = "wrap";
private void loadConfig() {
File json_file = getPageConfigFile();
JSONObject json=FileUtils.readJSONObjectFromFile(json_file);
if(json==null) {
json=new JSONObject();
JSONObject json = FileUtils.readJSONObjectFromFile(json_file);
if (json == null) {
json = new JSONObject();
}
PageConfig c=new PageConfig();
PageConfig c = new PageConfig();
c.applyDefaultFolderConfig();
// for low dpi devices, use icon filter by default
if(Utils.getStandardIconSize()==36) {
c.defaultShortcutConfig.iconFilter=true;
if (Utils.getStandardIconSize() == 36) {
c.defaultShortcutConfig.iconFilter = true;
}
c.loadFieldsFromJSONObject(json, c);
File icon_dir=getIconDir();
File icon_dir = getIconDir();
c.defaultItemConfig.loadAssociatedIcons(icon_dir, Item.NO_ID);
c.defaultShortcutConfig.loadAssociatedIcons(icon_dir, Item.NO_ID);
c.defaultFolderConfig.loadAssociatedIcons(icon_dir, Item.NO_ID);
// legacy with < 90
if(json.has(_backgroundColor) || json.has(_backgroundWallpaper) || json.has(_backgroundWallpaperScroll) || json.has(_backgroundWallpaperTintColor) || json.has(_backgroundWallpaperWidth) || json.has(_backgroundWallpaperHeight)) {
if (json.has(_backgroundColor) || json.has(_backgroundWallpaper) || json.has(_backgroundWallpaperScroll) || json.has(_backgroundWallpaperTintColor) || json.has(_backgroundWallpaperWidth) || json.has(_backgroundWallpaperHeight)) {
int backgroundColor = json.optInt(_backgroundColor, 0xff000000);
boolean backgroundWallpaper = json.optBoolean(_backgroundWallpaper, true);
boolean backgroundWallpaperScroll = json.optBoolean(_backgroundWallpaperScroll, false);
@ -614,7 +560,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
int backgroundWallpaperWidth = json.optInt(_backgroundWallpaperWidth, 0);
int backgroundWallpaperHeight = json.optInt(_backgroundWallpaperHeight, 0);
if(backgroundWallpaper) {
if (backgroundWallpaper) {
c.bgColor = backgroundWallpaperTintColor;
} else {
c.bgColor = backgroundColor;
@ -624,7 +570,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
c.bgSystemWPHeight = backgroundWallpaperHeight;
}
if(json.has(_gridColumnMode) || json.has(_gridColumnNum) || json.has(_gridColumnSize) || json.has(_gridRowMode) || json.has(_gridRowNum) || json.has(_gridRowSize)) {
if (json.has(_gridColumnMode) || json.has(_gridColumnNum) || json.has(_gridColumnSize) || json.has(_gridRowMode) || json.has(_gridRowNum) || json.has(_gridRowSize)) {
c.gridPColumnMode = c.gridLColumnMode = PageConfig.SizeMode.valueOf(json.optString(_gridColumnMode, PageConfig.SizeMode.NUM.name()));
c.gridPColumnNum = c.gridLColumnNum = json.optInt(_gridColumnNum, 5);
c.gridPColumnSize = c.gridLColumnSize = json.optInt(_gridColumnSize, 100);
@ -634,29 +580,29 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
}
// legacy with < 135
if(json.has(_layoutMode)) {
if (json.has(_layoutMode)) {
c.newOnGrid = c.defaultItemConfig.onGrid = "GRID".equals(json.optString(_layoutMode));
}
// legacy with < 208
boolean has_statusBarTransparent = true;
if(json.has(_statusBarTransparent)) {
if (json.has(_statusBarTransparent)) {
has_statusBarTransparent = json.optBoolean(_statusBarTransparent);
c.statusBarColor = has_statusBarTransparent ? 0 : Color.BLACK;
}
boolean has_navigationBarTransparent = true;
if(json.has(_navigationBarTransparent)) {
if (json.has(_navigationBarTransparent)) {
has_navigationBarTransparent = json.optBoolean(_navigationBarTransparent);
c.navigationBarColor = has_navigationBarTransparent ? 0 : Color.BLACK;
}
if(json.has(_transpBarOverlap)) {
if (json.has(_transpBarOverlap)) {
boolean overlap = json.optBoolean(_transpBarOverlap);
c.statusBarOverlap = overlap && has_statusBarTransparent;
c.navigationBarOverlap = overlap && has_navigationBarTransparent;
}
if(json.has(_wrap)) {
if (json.has(_wrap)) {
boolean wrap = json.optBoolean(_wrap);
c.wrapX = wrap;
c.wrapY = wrap;
@ -668,19 +614,19 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
private void loadItems() {
items=null;
items = null;
JSONObject json_data=FileUtils.readJSONObjectFromFile(getItemsFile());
JSONObject json_data = FileUtils.readJSONObjectFromFile(getItemsFile());
long t1 = BuildConfig.IS_BETA ? SystemClock.uptimeMillis() : 0;
if(json_data!=null) {
if (json_data != null) {
try {
JSONArray json_items=json_data.getJSONArray(JsonFields.ITEMS);
int l=json_items.length();
items=new ArrayList<>(l);
for(int i=0; i<l; i++) {
JSONObject o=json_items.getJSONObject(i);
Item item=Item.loadItemFromJSONObject(this, o);
if(item!=null) {
JSONArray json_items = json_data.getJSONArray(JsonFields.ITEMS);
int l = json_items.length();
items = new ArrayList<>(l);
for (int i = 0; i < l; i++) {
JSONObject o = json_items.getJSONObject(i);
Item item = Item.loadItemFromJSONObject(this, o);
if (item != null) {
items.add(item);
mListener.onPageItemLoaded(item);
}
@ -689,11 +635,11 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
e.printStackTrace();
}
}
if(items == null) {
items=new ArrayList<>();
if (items == null) {
items = new ArrayList<>();
}
if(BuildConfig.IS_BETA) {
Log.i("LL", "loadItems for page "+id+" in "+(SystemClock.uptimeMillis()-t1));
if (BuildConfig.IS_BETA) {
Log.i("LL", "loadItems for page " + id + " in " + (SystemClock.uptimeMillis() - t1));
}
}
@ -731,16 +677,16 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
//long t1= SystemClock.uptimeMillis();
try {
JSONArray json_items=new JSONArray();
JSONArray json_items = new JSONArray();
getAndCreateIconDir();
for(Item item : items) {
JSONObject json_item=item.toJSONObject();
for (Item item : items) {
JSONObject json_item = item.toJSONObject();
json_items.put(json_item);
if(item.getClass() == Widget.class) {
if (item.getClass() == Widget.class) {
ItemView v = Utils.findItemViewInAppScreens(item);
if(v != null && ((WidgetView)v).isGood()) {
if (v != null && ((WidgetView) v).isGood()) {
OutputStream os = null;
try {
os = new FileOutputStream(item.getDefaultIconFile());
@ -748,22 +694,160 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
Canvas canvas = new Canvas(b);
v.draw(canvas);
b.compress(Bitmap.CompressFormat.PNG, 100, os);
} catch(Throwable e) {
} catch (Throwable e) {
e.printStackTrace();
} finally {
if(os != null) try { os.close(); } catch(IOException e) {}
if (os != null) try {
os.close();
} catch (IOException e) {
}
}
}
}
}
JSONObject data=new JSONObject();
JSONObject data = new JSONObject();
data.put(JsonFields.ITEMS, json_items);
FileUtils.saveStringToFile(data.toString(), getItemsFile());
} catch(Exception e) {
} catch (Exception e) {
e.printStackTrace();
}
//Log.i("LL", "saveItems in "+(SystemClock.uptimeMillis()-t1));
}
public interface PageListener extends Item.OnItemEventListener {
void onPageLoaded(Page page);
void onPageRemoved(Page page);
void onPagePaused(Page page);
void onPageResumed(Page page);
void onPageModified(Page page);
// TODO move this to engine, this is not a page specific data
void onPageEditModeEntered(Page page);
void onPageEditModeLeaved(Page page);
void onPageItemLoaded(Item item);
void onPageItemDestroyed(Item item);
void onPageItemAdded(Item item);
void onPageItemBeforeRemove(Item item);
void onPageItemRemoved(Page page, Item item);
void onPageItemChanged(Page page, Item item);
void onPageItemZIndexChanged(Page page, int old_index, int new_index);
void onPageFolderWindowChanged(Page page, Folder folder);
}
public static class EmptyPageListener implements PageListener {
@Override
public void onPageLoaded(Page page) {
}
@Override
public void onPageRemoved(Page page) {
}
@Override
public void onPagePaused(Page page) {
}
@Override
public void onPageResumed(Page page) {
}
@Override
public void onPageModified(Page page) {
}
@Override
public void onPageEditModeEntered(Page page) {
}
@Override
public void onPageEditModeLeaved(Page page) {
}
@Override
public void onPageItemLoaded(Item item) {
}
@Override
public void onPageItemDestroyed(Item item) {
}
@Override
public void onPageItemAdded(Item item) {
}
@Override
public void onPageItemBeforeRemove(Item item) {
}
@Override
public void onPageItemRemoved(Page page, Item item) {
}
@Override
public void onPageItemChanged(Page page, Item item) {
}
@Override
public void onPageItemZIndexChanged(Page page, int old_index, int new_index) {
}
@Override
public void onPageFolderWindowChanged(Page page, Folder folder) {
}
@Override
public void onItemPaused(Item item) {
}
@Override
public void onItemResumed(Item item) {
}
@Override
public void onItemVisibilityChanged(Item item) {
}
@Override
public void onItemAlphaChanged(Item item) {
}
@Override
public void onItemTransformChanged(Item item, boolean fast) {
}
@Override
public void onItemCellChanged(Item item) {
}
@Override
public void onItemBindingsChanged(Item item, boolean apply) {
}
@Override
public void onItemError(Item item, Error error) {
}
@Override
public void onShortcutLabelChanged(Shortcut shortcut) {
}
@Override
public void onFolderPageIdChanged(Folder folder, int oldPageId) {
}
}
}

View file

@ -24,10 +24,10 @@ import java.io.IOException;
import java.util.ArrayList;
public class PageProcessor {
private ComponentName drawer_from;
private ComponentName drawer_to;
private String pkg_name_from;
private String pkg_name_to;
private final ComponentName drawer_from;
private final ComponentName drawer_to;
private final String pkg_name_from;
private final String pkg_name_to;
private boolean do_scale;
private float sx;
@ -39,7 +39,7 @@ public class PageProcessor {
// private int to_screen_width;
// private int to_screen_height;
// private int to_sb_height;
private boolean enforce_holo;
private boolean process_global_config;
@ -47,8 +47,8 @@ public class PageProcessor {
private SparseIntArray translated_script_ids;
public PageProcessor() {
ComponentName ll_app_drawer = new ComponentName(LLApp.LL_PKG_NAME, LLApp.LL_PKG_NAME+".activities.AppDrawer");
ComponentName llx_app_drawer = new ComponentName(LLApp.LLX_PKG_NAME, LLApp.LLX_PKG_NAME+".activities.AppDrawerX");
ComponentName ll_app_drawer = new ComponentName(LLApp.LL_PKG_NAME, LLApp.LL_PKG_NAME + ".activities.AppDrawer");
ComponentName llx_app_drawer = new ComponentName(LLApp.LLX_PKG_NAME, LLApp.LLX_PKG_NAME + ".activities.AppDrawerX");
String my_pkg_name = LLApp.get().getPackageName();
boolean is_llx = my_pkg_name.equals(LLApp.LLX_PKG_NAME);
@ -81,25 +81,25 @@ public class PageProcessor {
// this.to_screen_width = to_screen_width;
// this.to_screen_height = to_screen_height;
// this.to_sb_height = to_sb_height;
if(to_screen_width != 0) {
if (to_screen_width != 0) {
do_scale = true;
sx = to_screen_width / (float)from_screen_width;
sy = (to_screen_height - to_sb_height) / (float)(from_screen_height - from_sb_height);
sx = to_screen_width / (float) from_screen_width;
sy = (to_screen_height - to_sb_height) / (float) (from_screen_height - from_sb_height);
}
}
public void setEnforceHoloSelection(boolean enforce_holo) {
this.enforce_holo = enforce_holo;
}
public void postProcessPages(ArrayList<Page> pages) {
for(Page page : pages) {
for (Page page : pages) {
postProcessPage(page);
page.setModified();
page.save();
}
if(process_global_config && pages.size() > 0) {
if (process_global_config && pages.size() > 0) {
// TODO see whether this can be replaced with direct access of engine.getGlobalConfigFile()
File base_dir = pages.get(0).getEngine().getBaseDir();
File global_config_file = FileUtils.getGlobalConfigFile(base_dir);
@ -133,18 +133,18 @@ public class PageProcessor {
// check that the home page is valid, otherwise fix it
boolean valid = false;
for(Page page : pages) {
if(page.id == gc.homeScreen) {
for (Page page : pages) {
if (page.id == gc.homeScreen) {
valid = true;
break;
}
}
if(!valid) {
if (!valid) {
// use the first dashboard page
if(pages.size() > 0) {
for(Page page : pages) {
if (pages.size() > 0) {
for (Page page : pages) {
int id = page.id;
if(Page.isDashboard(id)) {
if (Page.isDashboard(id)) {
gc.homeScreen = id;
break;
}
@ -163,7 +163,7 @@ public class PageProcessor {
}
}
}
public void copyAndTranslatePage(Page pageFrom, LightningEngine engineTo, boolean keepAppWidgetId) {
byte[] buffer = new byte[1024];
@ -173,7 +173,7 @@ public class PageProcessor {
File baseDirFrom = pageFrom.getEngine().getBaseDir();
File baseDirTo = engineTo.getBaseDir();
Page p = engineTo.getPageManager().getPage(new_page_id);
if(p != null) {
if (p != null) {
throw new RuntimeException("Attempt to overwrite an existing page during import");
} else {
// make sure that the place is clean
@ -190,7 +190,7 @@ public class PageProcessor {
pageTo.config.copyFrom(pageFrom.config);
pageTo.items = new ArrayList<>(pageFrom.items.size());
for(Item old_item : pageFrom.items) {
for (Item old_item : pageFrom.items) {
int old_item_id = old_item.getId();
int new_item_id = Page.composeItemId(new_page_id, Page.getBaseItemId(old_item_id));
@ -200,7 +200,7 @@ public class PageProcessor {
try {
JSONObject json = old_item.toJSONObject();
json.put(JsonFields.ITEM_ID, new_item_id);
if(!keepAppWidgetId && old_item instanceof Widget) {
if (!keepAppWidgetId && old_item instanceof Widget) {
json.put(JsonFields.WIDGET_APP_WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
new_item = Item.loadItemFromJSONObject(pageTo, json);
@ -209,8 +209,8 @@ public class PageProcessor {
new_item = null;
}
if(new_item instanceof Folder) {
Folder f = (Folder)new_item;
if (new_item instanceof Folder) {
Folder f = (Folder) new_item;
f.setFolderPageId(translated_page_ids.get(f.getFolderPageId()));
}
@ -237,14 +237,14 @@ public class PageProcessor {
PageConfig c = page.config;
if(do_scale) {
if (do_scale) {
c.gridLColumnSize *= sx;
c.gridPColumnSize *= sx;
c.gridLRowSize *= sy;
c.gridPRowSize *= sy;
}
if(enforce_holo && c.defaultItemConfig.selectionEffect == ItemConfig.SelectionEffect.MATERIAL) {
if (enforce_holo && c.defaultItemConfig.selectionEffect == ItemConfig.SelectionEffect.MATERIAL) {
c.defaultItemConfig.selectionEffect = ItemConfig.SelectionEffect.HOLO;
}
@ -290,7 +290,7 @@ public class PageProcessor {
postProcessEventAction(pic.menu);
FolderConfig pfc = c.defaultFolderConfig;
if(do_scale && (pfc.wAH == Box.AlignH.CUSTOM || pfc.wAV == Box.AlignV.CUSTOM || pfc.wW!=0 || pfc.wH!=0)) {
if (do_scale && (pfc.wAH == Box.AlignH.CUSTOM || pfc.wAV == Box.AlignV.CUSTOM || pfc.wW != 0 || pfc.wH != 0)) {
pfc.wX *= sx;
pfc.wY *= sy;
pfc.wW *= sx;
@ -298,9 +298,9 @@ public class PageProcessor {
}
ArrayList<Item> items = page.items;
for(Item i : items) {
for (Item i : items) {
ItemConfig ic = i.getItemConfig();
if(ic != pic) {
if (ic != pic) {
postProcessEventAction(ic.tap);
postProcessEventAction(ic.longTap);
postProcessEventAction(ic.swipeLeft);
@ -313,8 +313,8 @@ public class PageProcessor {
postProcessEventAction(ic.menu);
}
if(!ic.onGrid && do_scale) {
i.setViewWidth((int)(i.getViewWidth() * sx));
if (!ic.onGrid && do_scale) {
i.setViewWidth((int) (i.getViewWidth() * sx));
i.setViewHeight((int) (i.getViewHeight() * sy));
Matrix m = i.getTransform();
m.getValues(matrix_values);
@ -325,24 +325,24 @@ public class PageProcessor {
}
Class<?> cls = i.getClass();
if(cls == StopPoint.class) {
postProcessEventAction(((StopPoint)i).getReachedAction());
} else if(cls == CustomView.class) {
if (cls == StopPoint.class) {
postProcessEventAction(((StopPoint) i).getReachedAction());
} else if (cls == CustomView.class) {
CustomView customView = (CustomView) i;
String newIdData = translateScriptAction(customView.onCreate);
if(newIdData != null) customView.onCreate = newIdData;
if (newIdData != null) customView.onCreate = newIdData;
newIdData = translateScriptAction(customView.onDestroy);
if(newIdData != null) customView.onDestroy = newIdData;
if (newIdData != null) customView.onDestroy = newIdData;
}
if(cls == Shortcut.class && page.id != Page.APP_DRAWER_PAGE) {
Shortcut s = (Shortcut)i;
if (cls == Shortcut.class && page.id != Page.APP_DRAWER_PAGE) {
Shortcut s = (Shortcut) i;
Intent intent = s.getIntent();
postProcessIntent(intent);
} else if(cls == Folder.class && do_scale) {
Folder f = (Folder)i;
} else if (cls == Folder.class && do_scale) {
Folder f = (Folder) i;
FolderConfig fc = f.getFolderConfig();
if(fc != pfc) {
if(fc.wAH == Box.AlignH.CUSTOM || fc.wAV == Box.AlignV.CUSTOM || fc.wW!=0 || fc.wH!=0) {
if (fc != pfc) {
if (fc.wAH == Box.AlignH.CUSTOM || fc.wAV == Box.AlignV.CUSTOM || fc.wW != 0 || fc.wH != 0) {
fc.wX *= sx;
fc.wY *= sy;
fc.wW *= sx;
@ -354,7 +354,7 @@ public class PageProcessor {
}
private String translateScriptAction(String data) {
if(data == null || translated_script_ids == null) {
if (data == null || translated_script_ids == null) {
return null;
}
@ -363,22 +363,22 @@ public class PageProcessor {
int oldScriptId = id_data.first;
int newScriptId = translated_script_ids.get(oldScriptId);
return Script.encodeIdAndData(newScriptId, id_data.second);
} catch(NumberFormatException e) {
} catch (NumberFormatException e) {
// pass
return null;
}
}
private String postProcessData(int action, String data) {
if(action == GlobalConfig.OPEN_FOLDER && translated_page_ids != null) {
if (action == GlobalConfig.OPEN_FOLDER && translated_page_ids != null) {
try {
int old_folder_page_id = Integer.parseInt(data);
int new_folder_page_id = translated_page_ids.get(old_folder_page_id);
return String.valueOf(new_folder_page_id);
} catch(NumberFormatException e) {
} catch (NumberFormatException e) {
// pass
}
} else if(action == GlobalConfig.RUN_SCRIPT && translated_script_ids != null) {
} else if (action == GlobalConfig.RUN_SCRIPT && translated_script_ids != null) {
return translateScriptAction(data);
}
@ -389,25 +389,25 @@ public class PageProcessor {
boolean modified = false;
ComponentName cn = intent.getComponent();
if(cn != null) {
if(cn.equals(drawer_from)) {
if (cn != null) {
if (cn.equals(drawer_from)) {
intent.setComponent(drawer_to);
modified = true;
} else if(cn.getPackageName().equals(pkg_name_from)) {
} else if (cn.getPackageName().equals(pkg_name_from)) {
intent.setComponent(new ComponentName(pkg_name_to, cn.getClassName()));
modified = true;
}
cn = intent.getComponent();
if(cn.getPackageName().equals(pkg_name_to)) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP) && translated_page_ids != null) {
if (cn.getPackageName().equals(pkg_name_to)) {
if (intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP) && translated_page_ids != null) {
int old_bookmark_page = intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, Page.NONE);
intent.putExtra(LightningIntent.INTENT_EXTRA_DESKTOP, translated_page_ids.get(old_bookmark_page));
modified = true;
} else {
EventAction ea = Utils.decodeEventActionFromLightningIntent(intent);
if(ea != null) {
if(postProcessEventAction(ea)) {
if (ea != null) {
if (postProcessEventAction(ea)) {
intent.removeExtra(LightningIntent.INTENT_EXTRA_ACTION);
intent.removeExtra(LightningIntent.INTENT_EXTRA_DATA);
intent.putExtra(LightningIntent.INTENT_EXTRA_EVENT_ACTION, JsonLoader.toJSONObject(ea, null).toString());
@ -416,10 +416,10 @@ public class PageProcessor {
}
}
if(do_scale) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
if (do_scale) {
if (intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
boolean absolute = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, true);
if(absolute) {
if (absolute) {
intent.putExtra(LightningIntent.INTENT_EXTRA_X, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_X, 0) * sx);
intent.putExtra(LightningIntent.INTENT_EXTRA_Y, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0) * sy);
modified = true;
@ -434,11 +434,11 @@ public class PageProcessor {
private boolean postProcessEventAction(EventAction ea) {
boolean res = false;
if(ea.action == GlobalConfig.LAUNCH_APP || ea.action == GlobalConfig.LAUNCH_SHORTCUT || ea.action == GlobalConfig.GO_DESKTOP_POSITION) {
if (ea.action == GlobalConfig.LAUNCH_APP || ea.action == GlobalConfig.LAUNCH_SHORTCUT || ea.action == GlobalConfig.GO_DESKTOP_POSITION) {
try {
Intent intent = Intent.parseUri(ea.data, 0);
boolean modified = postProcessIntent(intent);
if(modified) {
if (modified) {
ea.data = intent.toUri(0);
}
res = modified;
@ -447,13 +447,13 @@ public class PageProcessor {
}
} else {
String new_data = postProcessData(ea.action, ea.data);
if(new_data != null) {
if (new_data != null) {
ea.data = new_data;
res = true;
}
}
if(ea.next != null) {
if (ea.next != null) {
return postProcessEventAction(ea.next) || res;
} else {
return res;

View file

@ -18,13 +18,13 @@ import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.Drawable;
import net.pierrox.android.lsvg.SvgDrawable;
import net.pierrox.lightning_launcher.configuration.JsonFields;
import net.pierrox.lightning_launcher.configuration.ShortcutConfig;
import net.pierrox.lightning_launcher.configuration.ShortcutConfigStylable;
import net.pierrox.lightning_launcher.util.AnimationDecoder;
import net.pierrox.lightning_launcher.views.Graphics;
import net.pierrox.lightning_launcher.views.SharedAsyncGraphicsDrawable;
import net.pierrox.android.lsvg.SvgDrawable;
import net.pierrox.lightning_launcher.views.item.ItemView;
import net.pierrox.lightning_launcher.views.item.ShortcutView;
@ -42,57 +42,55 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
public static final String INTENT_EXTRA_APP_SHORTCUT_ID = "id";
public static final String INTENT_EXTRA_APP_SHORTCUT_PKG = "pkg";
public static final String INTENT_EXTRA_APP_SHORTCUT_DISABLED_MSG = "dis_msg";
private String mLabel;
private Intent mIntent;
protected ShortcutConfig mShortcutConfig;
private static final int[] mTmpSize = new int[2];
protected ShortcutConfig mShortcutConfig;
protected boolean mSharedShortcutConfig;
private String mLabel;
private Intent mIntent;
private SharedAsyncGraphicsDrawable mSharedAsyncGraphicsDrawable;
private Matrix mNormalizationMatrix;
public Shortcut(Page page) {
super(page);
}
public void setLabel(String label) {
mLabel=label;
mPage.setModified();
mPage.onShortcutLabelChanged(this);
}
public String getLabel() {
return mLabel;
}
public void setIntent(Intent intent) {
mIntent=intent;
public void setLabel(String label) {
mLabel = label;
mPage.setModified();
}
mPage.onShortcutLabelChanged(this);
}
public Intent getIntent() {
return mIntent;
}
public void setIntent(Intent intent) {
mIntent = intent;
mPage.setModified();
}
public boolean hasSharedShortcutConfig() {
return mSharedShortcutConfig;
}
@Override
public ShortcutConfig getShortcutConfig() {
return mShortcutConfig;
}
public ShortcutConfig getShortcutConfig() {
return mShortcutConfig;
}
@Override
public void setShortcutConfig(ShortcutConfig c) {
mSharedShortcutConfig=(mSharedShortcutConfig && c==mShortcutConfig);
mShortcutConfig=c;
}
public void setShortcutConfig(ShortcutConfig c) {
mSharedShortcutConfig = (mSharedShortcutConfig && c == mShortcutConfig);
mShortcutConfig = c;
}
@Override
public ShortcutConfig modifyShortcutConfig() {
if(mSharedShortcutConfig) {
if (mSharedShortcutConfig) {
// copy on write
ShortcutConfig sc = mShortcutConfig.clone();
mShortcutConfig = sc;
@ -117,32 +115,30 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
ShortcutConfig.getIconMaskFile(icon_dir, mId).delete();
}
@Override
public void createFromJSONObject(JSONObject o) throws JSONException {
readItemFromJSONObject(o);
JSONObject json_configuration=o.optJSONObject(JsonFields.SHORTCUT_CONFIGURATION);
readItemFromJSONObject(o);
JSONObject json_configuration = o.optJSONObject(JsonFields.SHORTCUT_CONFIGURATION);
mSharedShortcutConfig = json_configuration == null;
ShortcutConfig defaultShortcutConfig = mPage.config.defaultShortcutConfig;
if (mSharedShortcutConfig) {
mShortcutConfig= defaultShortcutConfig;
mShortcutConfig = defaultShortcutConfig;
} else {
mShortcutConfig= ShortcutConfig.readFromJsonObject(json_configuration, defaultShortcutConfig);
mShortcutConfig = ShortcutConfig.readFromJsonObject(json_configuration, defaultShortcutConfig);
mShortcutConfig.loadAssociatedIcons(mPage.getIconDir(), mId);
}
mLabel=o.optString(JsonFields.SHORTCUT_LABEL, null);
if(mLabel == null) {
mLabel = o.optString(JsonFields.SHORTCUT_LABEL, null);
if (mLabel == null) {
mLabel = mName;
}
try {
mIntent=Intent.parseUri(o.getString(JsonFields.SHORTCUT_INTENT), 0);
} catch (URISyntaxException e) {
throw new JSONException(e.getMessage());
}
}
try {
mIntent = Intent.parseUri(o.getString(JsonFields.SHORTCUT_INTENT), 0);
} catch (URISyntaxException e) {
throw new JSONException(e.getMessage());
}
}
@Override
public ItemView createView(Context context) {
@ -157,11 +153,11 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
public void init(int id, Rect cell_p, Rect cell_l, String label, Intent intent) {
super.init(id, cell_p, cell_l);
mShortcutConfig=mPage.config.defaultShortcutConfig;
mSharedShortcutConfig=true;
mShortcutConfig = mPage.config.defaultShortcutConfig;
mSharedShortcutConfig = true;
mLabel=label;
mIntent=intent;
mLabel = label;
mIntent = intent;
}
@Override
@ -172,7 +168,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
}
public SharedAsyncGraphicsDrawable getSharedAsyncGraphicsDrawable() {
if(mSharedAsyncGraphicsDrawable == null) {
if (mSharedAsyncGraphicsDrawable == null) {
mSharedAsyncGraphicsDrawable = new SharedAsyncGraphicsDrawable(this, null, mShortcutConfig.iconFilter);
}
return mSharedAsyncGraphicsDrawable;
@ -181,53 +177,53 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
public void recreateSharedAsyncGraphicsDrawable() {
mSharedAsyncGraphicsDrawable = new SharedAsyncGraphicsDrawable(this, null, mShortcutConfig.iconFilter);
}
protected void copyTo(Item item) {
super.copyTo(item);
Shortcut s=(Shortcut)item;
s.mLabel=mLabel;
s.mIntent=mIntent;
s.mShortcutConfig=mShortcutConfig;
s.mSharedShortcutConfig=mSharedShortcutConfig;
super.copyTo(item);
Shortcut s = (Shortcut) item;
s.mLabel = mLabel;
s.mIntent = mIntent;
s.mShortcutConfig = mShortcutConfig;
s.mSharedShortcutConfig = mSharedShortcutConfig;
}
@Override
public Item clone() {
Shortcut s=new Shortcut(mPage);
copyTo(s);
return s;
}
public Item clone() {
Shortcut s = new Shortcut(mPage);
copyTo(s);
return s;
}
public int getStdIconSize() {
return computeTotalWidth(Utils.getStandardIconSize());
return computeTotalWidth(Utils.getStandardIconSize());
}
@Override
public Graphics provideGraphics(SharedAsyncGraphicsDrawable sbd, Object data, int max_width, int max_height) {
File icon_file=getCustomIconFile();
if(!icon_file.exists()) {
icon_file=getDefaultIconFile();
File icon_file = getCustomIconFile();
if (!icon_file.exists()) {
icon_file = getDefaultIconFile();
}
Graphics graphics = null;
if(Utils.isGifFile(icon_file)) {
if (Utils.isGifFile(icon_file)) {
AnimationDecoder animationDecoder = Utils.loadGifDecoder(icon_file);
if(animationDecoder != null) {
if (animationDecoder != null) {
int[] size = getComposedImageSize(animationDecoder.getBitmap(), max_width, max_height);
graphics = new Graphics(animationDecoder, size[0], size[1]);
}
} else if(Utils.isSvgFile(icon_file)) {
} else if (Utils.isSvgFile(icon_file)) {
SvgDrawable svgDrawable = new SvgDrawable(icon_file);
graphics = new Graphics(svgDrawable);
}
if(graphics == null) {
if (graphics == null) {
Bitmap baseIcon = null;
try {
baseIcon = BitmapFactory.decodeStream(new FileInputStream(icon_file));
if(mShortcutConfig.iconSizeMode == ShortcutConfig.IconSizeMode.NORMALIZED) {
if (mShortcutConfig.iconSizeMode == ShortcutConfig.IconSizeMode.NORMALIZED) {
RectF box = computeNonEmptyIconBox(baseIcon);
if(box != null) {
if (box != null) {
final int width = baseIcon.getWidth();
final int height = baseIcon.getHeight();
int margin_w = width / 48;
@ -239,10 +235,10 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
mNormalizationMatrix.setRectToRect(box, normalized, Matrix.ScaleToFit.CENTER);
}
}
} catch(Throwable e) {
} catch (Throwable e) {
// catches IOException and OOM Error
}
if(baseIcon == null) {
if (baseIcon == null) {
baseIcon = Utils.getDefaultIcon();
}
@ -268,11 +264,11 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
box.right = w;
box.bottom = h;
boolean t=true, l=true, b=true, r=true;
boolean t = true, l = true, b = true, r = true;
int opaque_count;
for(int margin=0; margin<max_margin; margin++) {
if(t) {
for (int margin = 0; margin < max_margin; margin++) {
if (t) {
opaque_count = 0;
for (int x = margin; x < w - margin; x++) {
int pixel = bitmap.getPixel(x, margin);
@ -286,7 +282,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
}
}
}
if(b) {
if (b) {
opaque_count = 0;
for (int x = margin; x < w - margin; x++) {
final int y = h - 1 - margin;
@ -302,7 +298,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
}
}
if(l) {
if (l) {
opaque_count = 0;
for (int y = margin; y < h - margin; y++) {
int pixel = bitmap.getPixel(margin, y);
@ -317,7 +313,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
}
}
if(r) {
if (r) {
opaque_count = 0;
for (int y = margin; y < h - margin; y++) {
final int x = w - 1 - margin;
@ -337,7 +333,6 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
return t && l && b && r ? null : box;
}
private static int[] mTmpSize = new int[2];
private int[] getComposedImageSize(Bitmap baseBitmap, int maxWidth, int maxHeight) {
int width, height;
switch (mShortcutConfig.iconSizeMode) {
@ -351,8 +346,8 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
case FULL_SCALE_RATIO:
width = computeTotalWidth(baseBitmap.getWidth());
height = computeTotalHeight(baseBitmap.getHeight());
float scale = Math.min(maxWidth/(float)width, maxHeight/(float)height);
if(scale < 1) {
float scale = Math.min(maxWidth / (float) width, maxHeight / (float) height);
if (scale < 1) {
width = Math.round(width * scale);
height = Math.round(height * scale);
}
@ -380,10 +375,10 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
try {
finalBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
composeGraphics(baseBitmap, finalBitmap);
} catch(Throwable e) {
} catch (Throwable e) {
// catches OOM Error
}
if(finalBitmap == null) {
if (finalBitmap == null) {
finalBitmap = Utils.getDefaultIcon();
}
@ -392,24 +387,24 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
public int computeTotalWidth(int baseWidth) {
return (int)Math.ceil(baseWidth * mShortcutConfig.iconScale);
return (int) Math.ceil(baseWidth * mShortcutConfig.iconScale);
}
public int computeTotalHeight(int baseHeight) {
final ShortcutConfig c = mShortcutConfig;
final ShortcutConfig c = mShortcutConfig;
float scaledHeight = baseHeight * c.iconScale;
float total_height;
if(c.iconReflection) {
total_height=scaledHeight*(1+c.iconReflectionSize*c.iconReflectionScale-c.iconReflectionOverlap);
} else {
total_height=scaledHeight;
}
return (int)Math.ceil(total_height);
float total_height;
if (c.iconReflection) {
total_height = scaledHeight * (1 + c.iconReflectionSize * c.iconReflectionScale - c.iconReflectionOverlap);
} else {
total_height = scaledHeight;
}
return (int) Math.ceil(total_height);
}
@Override
public boolean composeGraphics(Bitmap baseIcon, Bitmap finalIcon) {
final ShortcutConfig c=mShortcutConfig;
final ShortcutConfig c = mShortcutConfig;
final Drawable back = c.iconBack;
final Drawable over = c.iconOver;
@ -434,29 +429,29 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
case NORMALIZED:
// force 1:1 ratio with one dimension set to std size
int innerSize = (int) Math.ceil(stdIconSize * c.iconEffectScale);
if(baseWidth > baseHeight) {
if (baseWidth > baseHeight) {
box_w = innerSize;
box_x = (stdIconSize - box_w)/2;
float scale = box_w / (float)baseWidth;
box_h = (int)Math.ceil(baseHeight*scale);
box_y = (stdIconSize - box_h)/2;
box_x = (stdIconSize - box_w) / 2;
float scale = box_w / (float) baseWidth;
box_h = (int) Math.ceil(baseHeight * scale);
box_y = (stdIconSize - box_h) / 2;
} else {
box_h = innerSize;
box_y = (stdIconSize - box_h)/2;
float scale = box_h / (float)baseHeight;
box_w = (int)Math.ceil(baseWidth*scale);
box_x = (stdIconSize - box_w)/2;
box_y = (stdIconSize - box_h) / 2;
float scale = box_h / (float) baseHeight;
box_w = (int) Math.ceil(baseWidth * scale);
box_x = (stdIconSize - box_w) / 2;
}
boxImage.set(box_x, box_y, box_x+box_w, box_y+box_h);
if(mNormalizationMatrix != null) {
boxImage.set(box_x, box_y, box_x + box_w, box_y + box_h);
if (mNormalizationMatrix != null) {
mNormalizationMatrix.mapRect(boxImage);
}
boxLayer.set(0, 0, stdIconSize, stdIconSize);
break;
case REAL:
box_w = (int)(baseWidth*c.iconScale*c.iconEffectScale);
box_h = (int)(baseHeight*c.iconScale*c.iconEffectScale);
box_w = (int) (baseWidth * c.iconScale * c.iconEffectScale);
box_h = (int) (baseHeight * c.iconScale * c.iconEffectScale);
// box_x = (finalWidth - box_w) / 2;
// if(box_x < 0) box_x = 0;
// box_y =(finalHeight - box_h) / 2;
@ -464,8 +459,8 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
// boxImage.set(box_x, box_y, box_x+box_w, box_y+box_h);
boxImage.set(0, 0, box_w, box_h);
box_w = (int)(baseWidth*c.iconScale);
box_h = (int)(baseHeight*c.iconScale);
box_w = (int) (baseWidth * c.iconScale);
box_h = (int) (baseHeight * c.iconScale);
boxLayer.set(0, 0, box_w, box_h);
break;
@ -473,11 +468,11 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
case FULL_SCALE_RATIO:
default:
float div = 1 + c.iconReflectionSize * c.iconReflectionScale - c.iconReflectionOverlap;
if(div == 0) div = 1;
int h = c.iconReflection ? (int)Math.ceil(finalHeight / div) : finalHeight;
if (div == 0) div = 1;
int h = c.iconReflection ? (int) Math.ceil(finalHeight / div) : finalHeight;
boolean keep_ratio = c.iconSizeMode == ShortcutConfig.IconSizeMode.FULL_SCALE_RATIO;
if(keep_ratio) {
float scale = Math.min(finalWidth/(float)baseWidth, h/(float)baseHeight);
if (keep_ratio) {
float scale = Math.min(finalWidth / (float) baseWidth, h / (float) baseHeight);
box_w = Math.round(scale * baseWidth * c.iconEffectScale);
box_h = Math.round(scale * baseHeight * c.iconEffectScale);
} else {
@ -486,9 +481,9 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
}
box_x = (finalWidth - box_w) / 2;
box_y = (h - box_h) / 2;
boxImage.set(box_x, box_y, box_x+box_w, box_y+box_h);
boxImage.set(box_x, box_y, box_x + box_w, box_y + box_h);
if(keep_ratio) {
if (keep_ratio) {
// boxLayer.set(box_x, box_y, box_x+box_w, box_y+box_h);
boxLayer.set(0, 0, finalWidth, h);
} else {
@ -498,13 +493,12 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
}
Canvas canvas = new Canvas(finalIcon);
Canvas canvas=new Canvas(finalIcon);
Paint paint=new Paint();
Paint paint = new Paint();
final int color_filter = c.iconColorFilter;
if(color_filter != 0xffffffff) {
if (color_filter != 0xffffffff) {
final float r = Color.red(color_filter) / 255f;
final float g = Color.green(color_filter) / 255f;
final float b = Color.blue(color_filter) / 255f;
@ -534,21 +528,21 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
}
if(c.iconReflection) {
float reflection_height = boxLayer.height()*c.iconReflectionSize*c.iconReflectionScale;
if (c.iconReflection) {
float reflection_height = boxLayer.height() * c.iconReflectionSize * c.iconReflectionScale;
// alays filter the reflection (minor overhead compared with other processing involved)
paint.setFilterBitmap(true);
canvas.save();
canvas.translate(0, boxLayer.bottom+boxLayer.bottom*c.iconReflectionScale-boxImage.height()*c.iconReflectionOverlap);
canvas.translate(0, boxLayer.bottom + boxLayer.bottom * c.iconReflectionScale - boxImage.height() * c.iconReflectionOverlap);
canvas.scale(1, -c.iconReflectionScale);
Paint mirror_icon_paint=new Paint();
LinearGradient linear_shader=new LinearGradient(0, 0, 0, reflection_height, 0xa0ffffff , 0x00ffffff, TileMode.CLAMP);
Paint mirror_icon_paint = new Paint();
LinearGradient linear_shader = new LinearGradient(0, 0, 0, reflection_height, 0xa0ffffff, 0x00ffffff, TileMode.CLAMP);
mirror_icon_paint.setShader(linear_shader);
mirror_icon_paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
if(back!=null) {
if (back != null) {
back.setBounds(boxLayer);
back.draw(canvas);
}
@ -556,11 +550,11 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
canvas.save();
canvas.drawBitmap(baseIcon, null, boxImage, paint);
canvas.restore();
if(mask!=null) {
if (mask != null) {
mask.setBounds(boxLayer);
mask.draw(canvas);
}
if(over!=null) {
if (over != null) {
over.setBounds(boxLayer);
over.draw(canvas);
}
@ -569,14 +563,14 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
canvas.restore(); // matrix
canvas.save();
canvas.translate(0, boxLayer.bottom-boxLayer.height()*c.iconReflectionOverlap+1);
canvas.translate(0, boxLayer.bottom - boxLayer.height() * c.iconReflectionOverlap + 1);
canvas.drawRect(0, 0, boxLayer.width(), reflection_height, mirror_icon_paint);
canvas.restore();
}
paint.setFilterBitmap(baseWidth != boxImage.width() || baseHeight != boxImage.height());
if(back!=null) {
if (back != null) {
back.setBounds(boxLayer);
back.draw(canvas);
}
@ -584,11 +578,11 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
canvas.save();
canvas.drawBitmap(baseIcon, null, boxImage, paint);
canvas.restore();
if(mask!=null) {
if (mask != null) {
mask.setBounds(boxLayer);
mask.draw(canvas);
}
if(over!=null) {
if (over != null) {
over.setBounds(boxLayer);
over.draw(canvas);
}

View file

@ -5,7 +5,7 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.*;
import android.graphics.Rect;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.configuration.JsonFields;
@ -17,121 +17,117 @@ import org.json.JSONObject;
public class Widget extends Item {
public static final int NO_APP_WIDGET_ID = -1;
// mAppWidgetId is -1 for LL Widget
private int mAppWidgetId=NO_APP_WIDGET_ID;
private ComponentName mComponentName;
public static final int NO_APP_WIDGET_ID = -1;
// mAppWidgetId is -1 for LL Widget
private int mAppWidgetId = NO_APP_WIDGET_ID;
private ComponentName mComponentName;
private String mAppWidgetLabel;
public Widget(Page page) {
super(page);
}
public Widget(Page page) {
super(page);
}
protected void copyTo(Item item) {
super.copyTo(item);
Widget w=(Widget)item;
w.mAppWidgetId=mAppWidgetId;
w.mComponentName=mComponentName;
}
@Override
public Item clone() {
Widget w=new Widget(mPage);
copyTo(w);
return w;
}
public int getAppWidgetId() {
return mAppWidgetId;
}
public void setAppWidgetId(int id) {
mAppWidgetId=id;
}
public static Widget createStatic(Page page, int id, Rect cell_p, Rect cell_l, ComponentName cn, int app_widget_id) {
Widget widget = new Widget(page);
public void setAppWidgetLabel(String label) {
mAppWidgetLabel = label;
widget.init(id, cell_p, cell_l);
widget.mComponentName = cn;
widget.mAppWidgetId = app_widget_id;
if (app_widget_id != NO_APP_WIDGET_ID) {
AppWidgetProviderInfo app_widget_info = AppWidgetManager.getInstance(LLApp.get()).getAppWidgetInfo(app_widget_id);
if (app_widget_info != null) {
widget.mAppWidgetLabel = app_widget_info.label;
}
}
return widget;
}
protected void copyTo(Item item) {
super.copyTo(item);
Widget w = (Widget) item;
w.mAppWidgetId = mAppWidgetId;
w.mComponentName = mComponentName;
}
@Override
public Item clone() {
Widget w = new Widget(mPage);
copyTo(w);
return w;
}
public int getAppWidgetId() {
return mAppWidgetId;
}
public void setAppWidgetId(int id) {
mAppWidgetId = id;
}
public String getAppWidgetLabel() {
return mAppWidgetLabel;
}
public ComponentName getComponentName() {
return mComponentName;
}
public void setComponentName(ComponentName cn) {
mComponentName=cn;
}
public boolean hasConfigurationScreen() {
AppWidgetManager app_widget_manager=AppWidgetManager.getInstance(LLApp.get());
AppWidgetProviderInfo app_widget_info=app_widget_manager.getAppWidgetInfo(mAppWidgetId);
if (app_widget_info!=null && app_widget_info.configure != null) {
return true;
} else {
return false;
}
public void setAppWidgetLabel(String label) {
mAppWidgetLabel = label;
}
public void onConfigure(Context context) {
AppWidgetManager app_widget_manager=AppWidgetManager.getInstance(LLApp.get());
AppWidgetProviderInfo app_widget_info=app_widget_manager.getAppWidgetInfo(mAppWidgetId);
if (app_widget_info!=null && app_widget_info.configure != null) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(app_widget_info.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
public ComponentName getComponentName() {
return mComponentName;
}
try {
context.startActivity(intent);
} catch(Exception e) {
// pass
}
}
}
public void setComponentName(ComponentName cn) {
mComponentName = cn;
}
@Override
public void onRemove(boolean keepResources) {
super.onRemove(keepResources);
if(!keepResources) {
LLApp.get().getAppWidgetHost().deleteAppWidgetId(mAppWidgetId);
}
}
public boolean hasConfigurationScreen() {
AppWidgetManager app_widget_manager = AppWidgetManager.getInstance(LLApp.get());
AppWidgetProviderInfo app_widget_info = app_widget_manager.getAppWidgetInfo(mAppWidgetId);
return app_widget_info != null && app_widget_info.configure != null;
}
@Override
public void createFromJSONObject(JSONObject o) throws JSONException {
readItemFromJSONObject(o);
mAppWidgetId=o.optInt(JsonFields.WIDGET_APP_WIDGET_ID, NO_APP_WIDGET_ID);
String cn=o.optString(JsonFields.WIDGET_COMPONENT_NAME, null);
if(cn!=null) {
mComponentName=ComponentName.unflattenFromString(cn);
}
mAppWidgetLabel =o.optString(JsonFields.WIDGET_LABEL, null);
}
public static Widget createStatic(Page page, int id, Rect cell_p, Rect cell_l, ComponentName cn, int app_widget_id) {
Widget widget=new Widget(page);
public void onConfigure(Context context) {
AppWidgetManager app_widget_manager = AppWidgetManager.getInstance(LLApp.get());
AppWidgetProviderInfo app_widget_info = app_widget_manager.getAppWidgetInfo(mAppWidgetId);
if (app_widget_info != null && app_widget_info.configure != null) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(app_widget_info.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
widget.init(id, cell_p, cell_l);
widget.mComponentName=cn;
widget.mAppWidgetId=app_widget_id;
if(app_widget_id != NO_APP_WIDGET_ID) {
AppWidgetProviderInfo app_widget_info = AppWidgetManager.getInstance(LLApp.get()).getAppWidgetInfo(app_widget_id);
if(app_widget_info != null) {
widget.mAppWidgetLabel = app_widget_info.label;
try {
context.startActivity(intent);
} catch (Exception e) {
// pass
}
}
}
return widget;
}
@Override
public void onRemove(boolean keepResources) {
super.onRemove(keepResources);
if (!keepResources) {
LLApp.get().getAppWidgetHost().deleteAppWidgetId(mAppWidgetId);
}
}
@Override
public ItemView createView(Context context) {
return new WidgetView(context, this);
}
@Override
public void createFromJSONObject(JSONObject o) throws JSONException {
readItemFromJSONObject(o);
mAppWidgetId = o.optInt(JsonFields.WIDGET_APP_WIDGET_ID, NO_APP_WIDGET_ID);
String cn = o.optString(JsonFields.WIDGET_COMPONENT_NAME, null);
if (cn != null) {
mComponentName = ComponentName.unflattenFromString(cn);
}
mAppWidgetLabel = o.optString(JsonFields.WIDGET_LABEL, null);
}
@Override
public ItemView createView(Context context) {
return new WidgetView(context, this);
}
}

View file

@ -41,35 +41,42 @@ import java.util.Iterator;
import java.util.List;
public class LightningEngine implements Page.PageListener {
public interface GlobalConfigListener {
void onGlobalConfigChanged(GlobalConfig newGlobalConfig);
}
private static final int GLOBAL_CONFIG_FILE_VERSION = 7;
/************************************** ANDROID 7.1 APP SHORTCUTS *************************************/
private static final String TOKEN_PIN_COUNT = "pinCount";
private final File mBaseDir;
private final PageManager mPageManager;
private final ScriptManager mScriptManager;
private final ScriptExecutor mScriptExecutor;
private final VariableManager mVariableManager;
private final BuiltinDataCollectors mBuiltinDataCollectors;
private final ArrayList<GlobalConfigListener> mGlobalConfigListeners = new ArrayList<>();
private final ArrayList<Page.PageListener> mPageListeners = new ArrayList<>();
private final Handler mHandler;
protected Context mContext;
private File mBaseDir;
private PageManager mPageManager;
private ScriptManager mScriptManager;
private ScriptExecutor mScriptExecutor;
private VariableManager mVariableManager;
private BuiltinDataCollectors mBuiltinDataCollectors;
private GlobalConfig mGlobalConfig;
private ArrayList<GlobalConfigListener> mGlobalConfigListeners = new ArrayList<>();
private ArrayList<Page.PageListener> mPageListeners = new ArrayList<>();
private Handler mHandler;
private int mResumedPagesCount;
private JSONObject mLaunchStatistics;
private JSONObject mAppShortcuts;
/***************************************** SAVE DATA ***********************************/
private final Runnable mSaveDataRunnable = new Runnable() {
@Override
public void run() {
mVariableManager.saveValues();
saveGlobalConfig();
saveLaunchStatistics();
saveAppShortcuts();
mPageManager.savePagesSync();
}
};
public LightningEngine(Context context, File baseDir) {
mContext = context;
@ -105,34 +112,33 @@ public class LightningEngine implements Page.PageListener {
}
/**
*
* @return true if upgrade of old free version
*/
public void migrate() {
if(shouldDoFirstTimeInit()) {
if (shouldDoFirstTimeInit()) {
// new install, nothing to migrate
return;
}
int from_version=mGlobalConfig.version;
if(from_version == 1) {
// from_version==1 && !first_time_install means global config never changed: unable to guess the migration path, but existing setup anyway
int from_version = mGlobalConfig.version;
if (from_version == 1) {
// from_version==1 && !first_time_install means global config never changed: unable to guess the migration path, but existing setup anyway
// save the global config now to keep track of the version now
saveGlobalConfig();
return;
}
return;
}
// migrate here (nothing yet)
// update the version number now
if(from_version<GLOBAL_CONFIG_FILE_VERSION) {
if (from_version < GLOBAL_CONFIG_FILE_VERSION) {
saveGlobalConfig();
}
}
public boolean shouldDoFirstTimeInit() {
int h = mGlobalConfig.homeScreen;
if(h != Page.FIRST_DASHBOARD_PAGE) {
if (h != Page.FIRST_DASHBOARD_PAGE) {
return false;
}
@ -182,25 +188,25 @@ public class LightningEngine implements Page.PageListener {
return page.findItemById(id);
}
public Pair<Page,Folder> getPageAndOpenerFromPath(ContainerPath path) {
public Pair<Page, Folder> getPageAndOpenerFromPath(ContainerPath path) {
int id = path.getLast();
if(path.getParent() == null) {
if (path.getParent() == null) {
Page page = getOrLoadPage(id);
if(id == Page.USER_MENU_PAGE) {
return new Pair<>(page, (Folder)page.findItemById(Utils.USER_MENU_ITEM_ID));
if (id == Page.USER_MENU_PAGE) {
return new Pair<>(page, (Folder) page.findItemById(Utils.USER_MENU_ITEM_ID));
} else {
return new Pair<>(page, null);
}
} else {
Item item = getItemById(id);
if(item instanceof Folder) {
if (item instanceof Folder) {
Folder folder = (Folder) item;
return new Pair<>(folder.getOrLoadFolderPage(), folder);
} else {
// not a folder? maybe a shortcut with a open folder action
if(item instanceof Shortcut) {
if (item instanceof Shortcut) {
Intent intent = ((Shortcut) item).getIntent();
if(LLApp.get().isLightningIntent(intent)) {
if (LLApp.get().isLightningIntent(intent)) {
EventAction eventAction = Utils.decodeEventActionFromLightningIntent(intent);
if (eventAction != null) {
int folderPage = Integer.parseInt(eventAction.data);
@ -226,7 +232,6 @@ public class LightningEngine implements Page.PageListener {
return mGlobalConfig.runScripts;
}
@Override
public void onPageModified(Page page) {
Utils.updateContainerIconIfNeeded(page);
@ -249,7 +254,7 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPageItemAdded(item);
Intent intent = getAppShortcutIntent(item);
if(intent != null) {
if (intent != null) {
String pkg = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG);
String id = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID);
pinAppShortcut(pkg, id);
@ -257,7 +262,7 @@ public class LightningEngine implements Page.PageListener {
Page page = item.getPage();
Utils.updateContainerIconIfNeeded(page);
if(item.getClass() == Shortcut.class && page.config.iconPack != null) {
if (item.getClass() == Shortcut.class && page.config.iconPack != null) {
IconPack.applyIconPackSync(mContext, page.config.iconPack, page, item.getId());
}
}
@ -270,7 +275,7 @@ public class LightningEngine implements Page.PageListener {
@Override
public void onPageItemRemoved(Page page, Item item) {
Intent intent = getAppShortcutIntent(item);
if(intent != null) {
if (intent != null) {
String pkg = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG);
String id = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID);
unpinAppShortcut(pkg, id);
@ -279,7 +284,7 @@ public class LightningEngine implements Page.PageListener {
// really hackish: reverse order so that the Lightning script object (which is the first to register) is evaluated last
// the reason is that scripts may be executed from other listeners and may need item data in the Lightning script object
for (int i = mPageListeners.size()-1; i>=0; i--) {
for (int i = mPageListeners.size() - 1; i >= 0; i--) {
Page.PageListener listener = mPageListeners.get(i);
listener.onPageItemRemoved(page, item);
}
@ -291,15 +296,16 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPageItemChanged(page, item);
// TODO move this into Screen
if(item instanceof Folder) {
onPageFolderWindowChanged(page, (Folder)item);
if (item instanceof Folder) {
onPageFolderWindowChanged(page, (Folder) item);
}
}
@Override
public void onPageItemZIndexChanged(Page page, int old_index, int new_index) {
Utils.updateContainerIconIfNeeded(page);
for (Page.PageListener listener : mPageListeners) listener.onPageItemZIndexChanged(page, old_index, new_index);
for (Page.PageListener listener : mPageListeners)
listener.onPageItemZIndexChanged(page, old_index, new_index);
}
@Override
@ -307,7 +313,7 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPagePaused(page);
mResumedPagesCount--;
if(mResumedPagesCount == 0) {
if (mResumedPagesCount == 0) {
mBuiltinDataCollectors.pause();
}
}
@ -316,7 +322,7 @@ public class LightningEngine implements Page.PageListener {
public void onPageResumed(Page page) {
for (Page.PageListener listener : mPageListeners) listener.onPageResumed(page);
if(mResumedPagesCount == 0) {
if (mResumedPagesCount == 0) {
mBuiltinDataCollectors.resume();
}
mResumedPagesCount++;
@ -324,7 +330,8 @@ public class LightningEngine implements Page.PageListener {
@Override
public void onPageFolderWindowChanged(Page page, Folder folder) {
for (Page.PageListener listener : mPageListeners) listener.onPageFolderWindowChanged(page, folder);
for (Page.PageListener listener : mPageListeners)
listener.onPageFolderWindowChanged(page, folder);
}
@Override
@ -363,7 +370,8 @@ public class LightningEngine implements Page.PageListener {
@Override
public void onItemTransformChanged(Item item, boolean fast) {
for (Page.PageListener listener : mPageListeners) listener.onItemTransformChanged(item, fast);
for (Page.PageListener listener : mPageListeners)
listener.onItemTransformChanged(item, fast);
}
@Override
@ -373,7 +381,8 @@ public class LightningEngine implements Page.PageListener {
@Override
public void onItemBindingsChanged(Item item, boolean apply) {
for (Page.PageListener listener : mPageListeners) listener.onItemBindingsChanged(item, apply);
for (Page.PageListener listener : mPageListeners)
listener.onItemBindingsChanged(item, apply);
}
@Override
@ -389,13 +398,14 @@ public class LightningEngine implements Page.PageListener {
@Override
public void onFolderPageIdChanged(Folder folder, int oldPageId) {
Utils.updateFolderIcon(folder);
for (Page.PageListener listener : mPageListeners) listener.onFolderPageIdChanged(folder, oldPageId);
for (Page.PageListener listener : mPageListeners)
listener.onFolderPageIdChanged(folder, oldPageId);
}
@Override
public void onPageRemoved(Page page) {
// see comment for onPageItemRemoved
for (int i = mPageListeners.size()-1; i>=0; i--) {
for (int i = mPageListeners.size() - 1; i >= 0; i--) {
Page.PageListener listener = mPageListeners.get(i);
listener.onPageRemoved(page);
}
@ -406,23 +416,6 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPageLoaded(page);
}
/***************************************** SAVE DATA ***********************************/
private Runnable mSaveDataRunnable = new Runnable() {
@Override
public void run() {
mVariableManager.saveValues();
saveGlobalConfig();
saveLaunchStatistics();
saveAppShortcuts();
mPageManager.savePagesSync();
}
};
public void saveData() {
cancelDelayedSaveData();
mSaveDataRunnable.run();
@ -453,19 +446,19 @@ public class LightningEngine implements Page.PageListener {
}
private void evaluateGlobalConfig() {
if(mGlobalConfig.screensOrder==null) {
if (mGlobalConfig.screensOrder == null) {
ArrayList<Integer> desktops = new ArrayList<>();
for(int i = Page.FIRST_DASHBOARD_PAGE; i<= Page.LAST_DASHBOARD_PAGE; i++) {
if(Page.getPageDir(mBaseDir, i).exists()) {
for (int i = Page.FIRST_DASHBOARD_PAGE; i <= Page.LAST_DASHBOARD_PAGE; i++) {
if (Page.getPageDir(mBaseDir, i).exists()) {
desktops.add(i);
}
}
int n=desktops.size();
int n = desktops.size();
int[] screens_order = new int[n];
String[] screens_name = new String[n];
for(int i=0; i<n; i++) {
for (int i = 0; i < n; i++) {
Integer page = desktops.get(i);
screens_order[i] = page;
screens_name[i] = String.valueOf(page);
@ -476,12 +469,12 @@ public class LightningEngine implements Page.PageListener {
}
// make sure that page directories are reserved
for(int p : mGlobalConfig.screensOrder) {
for (int p : mGlobalConfig.screensOrder) {
Page.getPageDir(mBaseDir, p).mkdirs();
}
Intent s=LLApp.get().getLockscreenServiceIntent();
if(s != null) {
Intent s = LLApp.get().getLockscreenServiceIntent();
if (s != null) {
if (mGlobalConfig.lockScreen != Page.NONE) {
mContext.startService(s);
} else {
@ -490,7 +483,7 @@ public class LightningEngine implements Page.PageListener {
}
s = LLApp.get().getWindowServiceIntent();
if(s != null && WindowService.isPermissionAllowed(mContext)) {
if (s != null && WindowService.isPermissionAllowed(mContext)) {
if (mGlobalConfig.overlayScreen != Page.NONE) {
mContext.startService(s);
} else {
@ -511,7 +504,7 @@ public class LightningEngine implements Page.PageListener {
public void notifyGlobalConfigChanged() {
evaluateGlobalConfig();
for(GlobalConfigListener l : mGlobalConfigListeners) {
for (GlobalConfigListener l : mGlobalConfigListeners) {
l.onGlobalConfigChanged(mGlobalConfig);
}
}
@ -519,12 +512,15 @@ public class LightningEngine implements Page.PageListener {
/************************************** LAUNCH STATISTICS *************************************/
public void updateLaunchStatisticsForShortcut(Shortcut shortcut) {
Intent intent=new Intent(shortcut.getIntent());
ComponentName cn=intent.getComponent();
if(cn!=null) {
String key=cn.flattenToShortString();
Intent intent = new Intent(shortcut.getIntent());
ComponentName cn = intent.getComponent();
if (cn != null) {
String key = cn.flattenToShortString();
int count = mLaunchStatistics.optInt(key);
try { mLaunchStatistics.put(key, count+1); } catch (JSONException e) { }
try {
mLaunchStatistics.put(key, count + 1);
} catch (JSONException e) {
}
}
}
@ -543,7 +539,7 @@ public class LightningEngine implements Page.PageListener {
private void loadLaunchStatistics() {
File statistics_file = FileUtils.getStatisticsFile(mBaseDir);
mLaunchStatistics = FileUtils.readJSONObjectFromFile(statistics_file);
if(mLaunchStatistics==null) {
if (mLaunchStatistics == null) {
mLaunchStatistics = new JSONObject();
}
}
@ -552,25 +548,21 @@ public class LightningEngine implements Page.PageListener {
try {
File out = FileUtils.getStatisticsFile(mBaseDir);
FileUtils.saveStringToFile(mLaunchStatistics.toString(), out);
} catch(Exception e) {
} catch (Exception e) {
// pass
}
}
/************************************** ANDROID 7.1 APP SHORTCUTS *************************************/
private static final String TOKEN_PIN_COUNT = "pinCount";
private void pinAppShortcut(String pkg, String id) {
int pinCount = adjustAppShortcutPinCount(pkg, id, 1);
if(pinCount == 1) {
if (pinCount == 1) {
updatePinnedAppShortcuts(pkg);
}
}
private void unpinAppShortcut(String pkg, String id) {
int pinCount = adjustAppShortcutPinCount(pkg, id, -1);
if(pinCount == 0) {
if (pinCount == 0) {
updatePinnedAppShortcuts(pkg);
}
}
@ -579,7 +571,7 @@ public class LightningEngine implements Page.PageListener {
private void updatePinnedAppShortcuts(String pkg) {
LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
List<String> pinnedAppShortcutIds = getPinnedAppShortcutIds(pkg);
if(launcherApps.hasShortcutHostPermission()) {
if (launcherApps.hasShortcutHostPermission()) {
launcherApps.pinShortcuts(pkg, pinnedAppShortcutIds, Process.myUserHandle());
}
}
@ -587,13 +579,13 @@ public class LightningEngine implements Page.PageListener {
private List<String> getPinnedAppShortcutIds(String pkg) {
ArrayList<String> ids = new ArrayList<>();
JSONObject appShortcutsForPackage = mAppShortcuts.optJSONObject(pkg);
if(appShortcutsForPackage != null) {
if (appShortcutsForPackage != null) {
Iterator<String> keys = appShortcutsForPackage.keys();
while(keys.hasNext()) {
while (keys.hasNext()) {
String id = keys.next();
JSONObject appShortcut = appShortcutsForPackage.optJSONObject(id);
int pinCount = appShortcut.optInt(TOKEN_PIN_COUNT, 0);
if(pinCount > 0) {
if (pinCount > 0) {
ids.add(id);
}
}
@ -604,7 +596,7 @@ public class LightningEngine implements Page.PageListener {
private int adjustAppShortcutPinCount(String pkg, String id, int increment) {
try {
JSONObject appShortcutsForPackage = mAppShortcuts.optJSONObject(pkg);
if(appShortcutsForPackage == null) {
if (appShortcutsForPackage == null) {
appShortcutsForPackage = new JSONObject();
mAppShortcuts.put(pkg, appShortcutsForPackage);
}
@ -642,7 +634,9 @@ public class LightningEngine implements Page.PageListener {
}
}
/** Return null if this isn't a Android 7.1 app shortcut */
/**
* Return null if this isn't a Android 7.1 app shortcut
*/
private Intent getAppShortcutIntent(Item item) {
if (item.getClass() == Shortcut.class) {
Shortcut shortcut = (Shortcut) item;
@ -662,13 +656,13 @@ public class LightningEngine implements Page.PageListener {
}
public int readCurrentPage(int default_page) {
String p=FileUtils.readFileContent(getCurrentPagerPageFile());
String p = FileUtils.readFileContent(getCurrentPagerPageFile());
int page;
try {
page=Integer.parseInt(p);
} catch(Exception e) {
page = Integer.parseInt(p);
} catch (Exception e) {
// catch NPE (if p==null) and NumberFormatException
page=default_page;
page = default_page;
}
return page;
}
@ -685,15 +679,15 @@ public class LightningEngine implements Page.PageListener {
public ArrayList<Folder> findAllFolderPageOpeners(int folder_page) {
ArrayList<Folder> openers = new ArrayList<>();
for(int n : mPageManager.getAllPagesIds()) {
if(n == folder_page && folder_page != Page.USER_MENU_PAGE) continue;
for (int n : mPageManager.getAllPagesIds()) {
if (n == folder_page && folder_page != Page.USER_MENU_PAGE) continue;
Page p = mPageManager.getOrLoadPage(n);
for(Item item : p.items) {
if(item instanceof Folder) {
Folder f=(Folder)item;
if(f.getFolderPageId()==folder_page) {
for (Item item : p.items) {
if (item instanceof Folder) {
Folder f = (Folder) item;
if (f.getFolderPageId() == folder_page) {
openers.add(f);
}
}
@ -704,22 +698,22 @@ public class LightningEngine implements Page.PageListener {
}
public Folder findFirstFolderPageOpener(int folder_page) {
if(!Page.isFolder(folder_page)) {
if (!Page.isFolder(folder_page)) {
return null;
}
ArrayList<Page> pages=mPageManager.getLoadedPages();
for(Page p : pages) {
ArrayList<Page> pages = mPageManager.getLoadedPages();
for (Page p : pages) {
// skip the page containing this item to avoid nasty recursive calls, except for the user menu which includes its opener
if(p.id == folder_page && folder_page != Page.USER_MENU_PAGE) continue;
if (p.id == folder_page && folder_page != Page.USER_MENU_PAGE) continue;
if(p.items==null) {
if (p.items == null) {
mPageManager.getOrLoadPage(p.id);
}
for(Item item : p.items) {
if(item instanceof Folder) {
Folder f=(Folder)item;
if(f.getFolderPageId()==folder_page) {
for (Item item : p.items) {
if (item instanceof Folder) {
Folder f = (Folder) item;
if (f.getFolderPageId() == folder_page) {
return f;
}
}
@ -727,22 +721,22 @@ public class LightningEngine implements Page.PageListener {
}
// not found in currently loaded pages, try again with unloaded pages
for(int n : mPageManager.getAllPagesIds()) {
for (int n : mPageManager.getAllPagesIds()) {
Page p = mPageManager.getPage(n);
if(p != null) {
if (p != null) {
// already traversed in the loop above
continue;
}
p = mPageManager.getOrLoadPage(n);
if(p.id == folder_page) continue;
if (p.id == folder_page) continue;
for(Item item : p.items) {
if(item instanceof Folder) {
Folder f=(Folder)item;
if(f.getFolderPageId()==folder_page) {
for (Item item : p.items) {
if (item instanceof Folder) {
Folder f = (Folder) item;
if (f.getFolderPageId() == folder_page) {
return f;
}
}
@ -753,15 +747,19 @@ public class LightningEngine implements Page.PageListener {
}
public void setFloatingDesktopVisibility(boolean visible) {
if(mGlobalConfig.overlayScreen != Page.NONE) {
if (mGlobalConfig.overlayScreen != Page.NONE) {
Intent f = LLApp.get().getWindowServiceIntent();
f.setAction(visible ? WindowService.INTENT_ACTION_SHOW : WindowService.INTENT_ACTION_HIDE);
mContext.startService(f);
}
}
public interface GlobalConfigListener {
void onGlobalConfigChanged(GlobalConfig newGlobalConfig);
}
public class PageManager {
private ArrayList<Page> mPages = new ArrayList<>();
private final ArrayList<Page> mPages = new ArrayList<>();
private PageManager() {
}
@ -772,13 +770,13 @@ public class LightningEngine implements Page.PageListener {
public int[] getAllPagesIds() {
String[] allPageNames = FileUtils.getPagesDir(mBaseDir).list();
if(allPageNames == null) {
if (allPageNames == null) {
return new int[0];
}
int length = allPageNames.length;
int[] allPagesIds = new int[length];
for(int n=0; n<length; n++) {
for (int n = 0; n < length; n++) {
allPagesIds[n] = Integer.parseInt(allPageNames[n]);
}
return allPagesIds;
@ -793,8 +791,8 @@ public class LightningEngine implements Page.PageListener {
}
public Page getPage(int id) {
for(Page page : mPages) {
if(page.id == id) {
for (Page page : mPages) {
if (page.id == id) {
return page;
}
}
@ -804,7 +802,7 @@ public class LightningEngine implements Page.PageListener {
public Page getOrLoadPage(int id) {
Page page = getPage(id);
if(page != null) {
if (page != null) {
return page;
}
@ -817,7 +815,7 @@ public class LightningEngine implements Page.PageListener {
}
public void savePagesSync() {
for(Page p : new ArrayList<Page>(mPages)) {
for (Page p : new ArrayList<Page>(mPages)) {
p.save();
}
}
@ -848,7 +846,7 @@ public class LightningEngine implements Page.PageListener {
// reserve copied page ids
SparseIntArray translated_page_ids = new SparseIntArray();
for(Page to_translate : pages_to_copy) {
for (Page to_translate : pages_to_copy) {
int new_page_id = Page.reservePage(mBaseDir, to_translate.isFolder());
translated_page_ids.put(to_translate.id, new_page_id);
}
@ -856,7 +854,7 @@ public class LightningEngine implements Page.PageListener {
// copy and translate pages
PageProcessor page_processor = new PageProcessor();
page_processor.setTranslatedPageIds(translated_page_ids);
for(Page to_copy : pages_to_copy) {
for (Page to_copy : pages_to_copy) {
page_processor.copyAndTranslatePage(to_copy, LightningEngine.this, keepAppWidgetId);
}

View file

@ -15,20 +15,20 @@ import net.pierrox.lightning_launcher.R;
private static final String VAR_VOLTAGE = "bat_voltage";
private static final String VAR_PLUGGED = "bat_plugged";
private Context mContext;
private BroadcastReceiver mBatteryReceiver;
private final Context mContext;
private final BroadcastReceiver mBatteryReceiver;
/*package*/ BatteryDataCollector(Context context, final VariableManager vm) {
mContext = context;
mBatteryReceiver=new BroadcastReceiver() {
mBatteryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int level=intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale=intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
int status=intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
int voltage=intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
int plugged=intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
vm.setVariable(VAR_LEVEL, level*100/scale);
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
vm.setVariable(VAR_LEVEL, level * 100 / scale);
vm.setVariable(VAR_STATUS, status);
vm.setVariable(VAR_VOLTAGE, voltage);
vm.setVariable(VAR_PLUGGED, plugged);
@ -53,7 +53,7 @@ import net.pierrox.lightning_launcher.R;
@Override
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[] {
return new BuiltinVariable[]{
new BuiltinVariable(VAR_LEVEL, resources.getString(R.string.bv_batl)),
new BuiltinVariable(VAR_STATUS, resources.getString(R.string.bv_batst)),
new BuiltinVariable(VAR_VOLTAGE, resources.getString(R.string.bv_batv)),

View file

@ -12,8 +12,8 @@ public final class Binding {
}
public boolean equals(Binding other) {
if(target == null && other.target!=null || (target != null && !target.equals(other.target))) return false;
if(formula == null && other.formula!=null || (formula != null && !formula.equals(other.formula))) return false;
return true;
if (target == null && other.target != null || (target != null && !target.equals(other.target)))
return false;
return (formula != null || other.formula == null) && (formula == null || formula.equals(other.formula));
}
}

View file

@ -12,10 +12,10 @@ public class BuiltinDataCollectors {
private static final String VAR_SCREEN_WIDTH = "screen_width";
private static final String VAR_SCREEN_HEIGHT = "screen_height";
private Pair<String,BuiltinVariable[]>[] mBuiltinVariables;
private Handler mHandler;
private VariableManager mVariableManager;
private DataCollector[] mDataCollectors;
private final Pair<String, BuiltinVariable[]>[] mBuiltinVariables;
private final Handler mHandler;
private final VariableManager mVariableManager;
private final DataCollector[] mDataCollectors;
private int mResumedCount;
public BuiltinDataCollectors(Context context, VariableManager vm) {
@ -26,7 +26,7 @@ public class BuiltinDataCollectors {
StorageDataCollector storageDataCollector = new StorageDataCollector(context, mHandler, mVariableManager);
BatteryDataCollector batteryDataCollector = new BatteryDataCollector(context, mVariableManager);
CpuDataCollector cpuDataCollector = new CpuDataCollector(mHandler, mVariableManager);
mDataCollectors = new DataCollector[] {
mDataCollectors = new DataCollector[]{
timeDataCollector,
storageDataCollector,
batteryDataCollector,
@ -35,13 +35,13 @@ public class BuiltinDataCollectors {
Resources resources = context.getResources();
BuiltinVariable[] screen_variables = new BuiltinVariable[] {
new BuiltinVariable(VAR_SCREEN_ORIENTATION, resources.getString(R.string.bv_o)),
new BuiltinVariable(VAR_SCREEN_WIDTH, resources.getString(R.string.gb_w)),
new BuiltinVariable(VAR_SCREEN_HEIGHT, resources.getString(R.string.gb_h)),
BuiltinVariable[] screen_variables = new BuiltinVariable[]{
new BuiltinVariable(VAR_SCREEN_ORIENTATION, resources.getString(R.string.bv_o)),
new BuiltinVariable(VAR_SCREEN_WIDTH, resources.getString(R.string.gb_w)),
new BuiltinVariable(VAR_SCREEN_HEIGHT, resources.getString(R.string.gb_h)),
};
mBuiltinVariables = new Pair[] {
mBuiltinVariables = new Pair[]{
new Pair<>(resources.getString(R.string.bvc_dt), timeDataCollector.getBuiltinVariables(resources)),
new Pair<>(resources.getString(R.string.bvc_screen), screen_variables),
new Pair<>(resources.getString(R.string.bvc_stor), storageDataCollector.getBuiltinVariables(resources)),
@ -51,11 +51,11 @@ public class BuiltinDataCollectors {
}
public void end() {
for(DataCollector collector : mDataCollectors) collector.end();
for (DataCollector collector : mDataCollectors) collector.end();
}
public void resume() {
if(mResumedCount == 0) {
if (mResumedCount == 0) {
for (DataCollector collector : mDataCollectors) collector.onResume();
}
mResumedCount++;
@ -63,12 +63,12 @@ public class BuiltinDataCollectors {
public void pause() {
mResumedCount--;
if(mResumedCount == 0) {
for(DataCollector collector : mDataCollectors) collector.onPause();
if (mResumedCount == 0) {
for (DataCollector collector : mDataCollectors) collector.onPause();
}
}
public Pair<String,BuiltinVariable[]>[] getBuiltinVariables() {
public Pair<String, BuiltinVariable[]>[] getBuiltinVariables() {
return mBuiltinVariables;
}

View file

@ -10,70 +10,22 @@ import java.io.FileReader;
import java.io.IOException;
public class CpuDataCollector extends PollingDataCollector {
// private static String VAR_COUNT = "cpu_count";
private static String VAR_USAGE = "cpu_usage";
private static String VAR_USER = "cpu_user";
private static String VAR_NICE = "cpu_nice";
private static String VAR_SYSTEM = "cpu_system";
private static String VAR_IDLE = "cpu_idle";
private static String VAR_IOWAIT = "cpu_iowait";
private static String VAR_IRQ = "cpu_irq";
private static String VAR_SOFTIRQ = "cpu_softirq";
private static class CpuUsage {
long user;
long nice;
long system;
long idle;
long iowait;
long irq;
long softirq;
long total;
}
// private static String VAR_COUNT = "cpu_count";
private static final String VAR_USAGE = "cpu_usage";
private static final String VAR_USER = "cpu_user";
private static final String VAR_NICE = "cpu_nice";
private static final String VAR_SYSTEM = "cpu_system";
private static final String VAR_IDLE = "cpu_idle";
private static final String VAR_IOWAIT = "cpu_iowait";
private static final String VAR_IRQ = "cpu_irq";
private static final String VAR_SOFTIRQ = "cpu_softirq";
private CpuUsage mPreviousUsage;
private CpuUsage mCurrentUsage;
public CpuDataCollector(Handler handler, VariableManager vm) {
super(2500, handler, vm);
mPreviousUsage = new CpuUsage();
mCurrentUsage = new CpuUsage();
readProcStat(mPreviousUsage);
}
@Override
protected void collectData() {
try {
// the normal period will be 2500+500, the initial collect time will be 500 only (faster refresh at startup)
Thread.sleep(500);
} catch (InterruptedException e) {
// pass
}
readProcStat(mCurrentUsage);
mHandler.post(mSetVariablesRunnable);
}
@Override
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[] {
new BuiltinVariable(VAR_USAGE, resources.getString(R.string.bv_cu)),
new BuiltinVariable(VAR_USER, resources.getString(R.string.bv_cr)),
new BuiltinVariable(VAR_NICE, resources.getString(R.string.bv_cn)),
new BuiltinVariable(VAR_SYSTEM, resources.getString(R.string.bv_cs)),
new BuiltinVariable(VAR_IDLE, resources.getString(R.string.bv_ci)),
new BuiltinVariable(VAR_IOWAIT, resources.getString(R.string.bv_co)),
new BuiltinVariable(VAR_IRQ, resources.getString(R.string.bv_cq)),
new BuiltinVariable(VAR_SOFTIRQ, resources.getString(R.string.bv_cf)),
};
}
private Runnable mSetVariablesRunnable = new Runnable() {
private final Runnable mSetVariablesRunnable = new Runnable() {
@Override
public void run() {
long delta = mCurrentUsage.total - mPreviousUsage.total;
if(delta != 0) {
if (delta != 0) {
long user = (mCurrentUsage.total - mCurrentUsage.idle) - (mPreviousUsage.total - mPreviousUsage.idle);
mVariableManager.edit();
mVariableManager.setVariable(VAR_USAGE, percent(user, delta));
@ -93,8 +45,43 @@ public class CpuDataCollector extends PollingDataCollector {
}
};
public CpuDataCollector(Handler handler, VariableManager vm) {
super(2500, handler, vm);
mPreviousUsage = new CpuUsage();
mCurrentUsage = new CpuUsage();
readProcStat(mPreviousUsage);
}
private static int percent(long value, long total) {
return (int)(value*100/total);
return (int) (value * 100 / total);
}
@Override
protected void collectData() {
try {
// the normal period will be 2500+500, the initial collect time will be 500 only (faster refresh at startup)
Thread.sleep(500);
} catch (InterruptedException e) {
// pass
}
readProcStat(mCurrentUsage);
mHandler.post(mSetVariablesRunnable);
}
@Override
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[]{
new BuiltinVariable(VAR_USAGE, resources.getString(R.string.bv_cu)),
new BuiltinVariable(VAR_USER, resources.getString(R.string.bv_cr)),
new BuiltinVariable(VAR_NICE, resources.getString(R.string.bv_cn)),
new BuiltinVariable(VAR_SYSTEM, resources.getString(R.string.bv_cs)),
new BuiltinVariable(VAR_IDLE, resources.getString(R.string.bv_ci)),
new BuiltinVariable(VAR_IOWAIT, resources.getString(R.string.bv_co)),
new BuiltinVariable(VAR_IRQ, resources.getString(R.string.bv_cq)),
new BuiltinVariable(VAR_SOFTIRQ, resources.getString(R.string.bv_cf)),
};
}
private void readProcStat(CpuUsage out) {
@ -115,7 +102,20 @@ public class CpuDataCollector extends PollingDataCollector {
} catch (IOException e) {
// pass
} finally {
if(br != null) try { br.close(); } catch (IOException e) { /*pass*/ }
if (br != null) try {
br.close();
} catch (IOException e) { /*pass*/ }
}
}
private static class CpuUsage {
long user;
long nice;
long system;
long idle;
long iowait;
long irq;
long softirq;
long total;
}
}

View file

@ -3,8 +3,11 @@ package net.pierrox.lightning_launcher.engine.variable;
import android.content.res.Resources;
public interface DataCollector {
public void onPause();
public void onResume();
public void end();
public BuiltinVariable[] getBuiltinVariables(Resources resources);
void onPause();
void onResume();
void end();
BuiltinVariable[] getBuiltinVariables(Resources resources);
}

View file

@ -3,7 +3,7 @@ package net.pierrox.lightning_launcher.engine.variable;
import android.os.Handler;
/*package*/ abstract class PollingDataCollector extends Thread implements DataCollector {
private int mPeriod;
private final int mPeriod;
protected Handler mHandler;
protected VariableManager mVariableManager;
private boolean mPaused;
@ -22,7 +22,7 @@ import android.os.Handler;
do {
collectData();
if(mEnd) break;
if (mEnd) break;
try {
sleep(mPeriod);
@ -30,7 +30,7 @@ import android.os.Handler;
// interrupted, will likely end
}
if(mPaused) {
if (mPaused) {
synchronized (this) {
try {
wait();
@ -39,7 +39,7 @@ import android.os.Handler;
}
}
}
} while(!mEnd);
} while (!mEnd);
}
@Override

View file

@ -21,34 +21,8 @@ import java.io.File;
private static final String VAR_INT_TOTAL_H = "int_total_h";
private static final String VAR_INT_FREE_H = "int_free_h";
private Context mContext;
public StorageDataCollector(Context context, Handler handler, VariableManager vm) {
super(10000, handler, vm);
mContext = context;
mSetVariablesRunnable.run();
}
@Override
protected void collectData() {
mHandler.post(mSetVariablesRunnable);
}
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[] {
new BuiltinVariable(VAR_EXT_TOTAL_H, resources.getString(R.string.bv_eth)),
new BuiltinVariable(VAR_EXT_FREE_H, resources.getString(R.string.bv_efh)),
new BuiltinVariable(VAR_INT_TOTAL_H, resources.getString(R.string.bv_ith)),
new BuiltinVariable(VAR_INT_FREE_H, resources.getString(R.string.bv_ifh)),
new BuiltinVariable(VAR_EXT_TOTAL, resources.getString(R.string.bv_et)),
new BuiltinVariable(VAR_EXT_FREE, resources.getString(R.string.bv_ef)),
new BuiltinVariable(VAR_INT_TOTAL, resources.getString(R.string.bv_it)),
new BuiltinVariable(VAR_INT_FREE, resources.getString(R.string.bv_if)),
};
}
private Runnable mSetVariablesRunnable = new Runnable() {
private final Context mContext;
private final Runnable mSetVariablesRunnable = new Runnable() {
@Override
public void run() {
long int_free;
@ -68,9 +42,9 @@ import java.io.File;
block_size = stat.getBlockSize();
total_blocks = stat.getBlockCount();
available_blocks = stat.getAvailableBlocks();
int_free = available_blocks*block_size;
int_total = total_blocks*block_size;
} catch(IllegalArgumentException e) {
int_free = available_blocks * block_size;
int_total = total_blocks * block_size;
} catch (IllegalArgumentException e) {
int_free = 0;
int_total = 0;
}
@ -83,7 +57,7 @@ import java.io.File;
available_blocks = stat.getAvailableBlocks();
ext_free = available_blocks * block_size;
ext_total = total_blocks * block_size;
} catch(IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
ext_free = 0;
ext_total = 0;
}
@ -100,4 +74,29 @@ import java.io.File;
mVariableManager.commit();
}
};
public StorageDataCollector(Context context, Handler handler, VariableManager vm) {
super(10000, handler, vm);
mContext = context;
mSetVariablesRunnable.run();
}
@Override
protected void collectData() {
mHandler.post(mSetVariablesRunnable);
}
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[]{
new BuiltinVariable(VAR_EXT_TOTAL_H, resources.getString(R.string.bv_eth)),
new BuiltinVariable(VAR_EXT_FREE_H, resources.getString(R.string.bv_efh)),
new BuiltinVariable(VAR_INT_TOTAL_H, resources.getString(R.string.bv_ith)),
new BuiltinVariable(VAR_INT_FREE_H, resources.getString(R.string.bv_ifh)),
new BuiltinVariable(VAR_EXT_TOTAL, resources.getString(R.string.bv_et)),
new BuiltinVariable(VAR_EXT_FREE, resources.getString(R.string.bv_ef)),
new BuiltinVariable(VAR_INT_TOTAL, resources.getString(R.string.bv_it)),
new BuiltinVariable(VAR_INT_FREE, resources.getString(R.string.bv_if)),
};
}
}

View file

@ -22,49 +22,20 @@ public class TimeDataCollector extends PollingDataCollector {
private static final String VAR_DAY_NAME = "ll_day_name";
private static final String VAR_MONTH_NAME = "ll_month_name";
private SimpleDateFormat mDfSecond = new SimpleDateFormat("ss");
private SimpleDateFormat mDfMinute = new SimpleDateFormat("mm");
private SimpleDateFormat mDfHour12 = new SimpleDateFormat("hh");
private SimpleDateFormat mDfHour24 = new SimpleDateFormat("HH");
private SimpleDateFormat mDfDay = new SimpleDateFormat("dd");
private SimpleDateFormat mDfMonth = new SimpleDateFormat("MM");
private SimpleDateFormat mDfWeek = new SimpleDateFormat("w");
private SimpleDateFormat mDfYear = new SimpleDateFormat("yyyy");
private SimpleDateFormat mDfAmPm = new SimpleDateFormat("a");
private SimpleDateFormat mDfDayName = new SimpleDateFormat("EEEE");
private SimpleDateFormat mDfMonthName = new SimpleDateFormat("MMMM");
private final SimpleDateFormat mDfSecond = new SimpleDateFormat("ss");
private final SimpleDateFormat mDfMinute = new SimpleDateFormat("mm");
private final SimpleDateFormat mDfHour12 = new SimpleDateFormat("hh");
private final SimpleDateFormat mDfHour24 = new SimpleDateFormat("HH");
private final SimpleDateFormat mDfDay = new SimpleDateFormat("dd");
private final SimpleDateFormat mDfMonth = new SimpleDateFormat("MM");
private final SimpleDateFormat mDfWeek = new SimpleDateFormat("w");
private final SimpleDateFormat mDfYear = new SimpleDateFormat("yyyy");
private final SimpleDateFormat mDfAmPm = new SimpleDateFormat("a");
private final SimpleDateFormat mDfDayName = new SimpleDateFormat("EEEE");
private final SimpleDateFormat mDfMonthName = new SimpleDateFormat("MMMM");
private int mPreviousSecond = -1;
public TimeDataCollector(Handler handler, VariableManager vm) {
super(1000, handler, vm);
mSetVariablesRunnable.run();
}
@Override
protected void collectData() {
mHandler.post(mSetVariablesRunnable);
}
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[] {
new BuiltinVariable(VAR_SECOND, resources.getString(R.string.bv_sec)),
new BuiltinVariable(VAR_MINUTE, resources.getString(R.string.bv_min)),
new BuiltinVariable(VAR_HOUR12, resources.getString(R.string.bv_h12)),
new BuiltinVariable(VAR_HOUR24, resources.getString(R.string.bv_h24)),
new BuiltinVariable(VAR_AM_PM, resources.getString(R.string.bv_ampm)),
new BuiltinVariable(VAR_DAY, resources.getString(R.string.bv_day)),
new BuiltinVariable(VAR_MONTH, resources.getString(R.string.bv_mon)),
new BuiltinVariable(VAR_WEEK, resources.getString(R.string.bv_week)),
new BuiltinVariable(VAR_YEAR, resources.getString(R.string.bv_year)),
new BuiltinVariable(VAR_DAY_NAME, resources.getString(R.string.bv_dayn)),
new BuiltinVariable(VAR_MONTH_NAME, resources.getString(R.string.bv_monn)),
new BuiltinVariable(VAR_TIMESTAMP, resources.getString(R.string.bv_ts)),
};
}
private Runnable mSetVariablesRunnable = new Runnable() {
private final Runnable mSetVariablesRunnable = new Runnable() {
@Override
public void run() {
// text fields, but some of them can be converted to integer
@ -72,8 +43,8 @@ public class TimeDataCollector extends PollingDataCollector {
int second = now.getSeconds();
mVariableManager.edit();
mVariableManager.setVariable(VAR_SECOND, mDfSecond.format(now));
mVariableManager.setVariable(VAR_TIMESTAMP, now.getTime()/1000);
if(mPreviousSecond == -1 || second<mPreviousSecond) {
mVariableManager.setVariable(VAR_TIMESTAMP, now.getTime() / 1000);
if (mPreviousSecond == -1 || second < mPreviousSecond) {
mVariableManager.setVariable(VAR_MINUTE, mDfMinute.format(now));
mVariableManager.setVariable(VAR_HOUR12, mDfHour12.format(now));
mVariableManager.setVariable(VAR_HOUR24, mDfHour24.format(now));
@ -90,6 +61,34 @@ public class TimeDataCollector extends PollingDataCollector {
}
};
public TimeDataCollector(Handler handler, VariableManager vm) {
super(1000, handler, vm);
mSetVariablesRunnable.run();
}
@Override
protected void collectData() {
mHandler.post(mSetVariablesRunnable);
}
public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[]{
new BuiltinVariable(VAR_SECOND, resources.getString(R.string.bv_sec)),
new BuiltinVariable(VAR_MINUTE, resources.getString(R.string.bv_min)),
new BuiltinVariable(VAR_HOUR12, resources.getString(R.string.bv_h12)),
new BuiltinVariable(VAR_HOUR24, resources.getString(R.string.bv_h24)),
new BuiltinVariable(VAR_AM_PM, resources.getString(R.string.bv_ampm)),
new BuiltinVariable(VAR_DAY, resources.getString(R.string.bv_day)),
new BuiltinVariable(VAR_MONTH, resources.getString(R.string.bv_mon)),
new BuiltinVariable(VAR_WEEK, resources.getString(R.string.bv_week)),
new BuiltinVariable(VAR_YEAR, resources.getString(R.string.bv_year)),
new BuiltinVariable(VAR_DAY_NAME, resources.getString(R.string.bv_dayn)),
new BuiltinVariable(VAR_MONTH_NAME, resources.getString(R.string.bv_monn)),
new BuiltinVariable(VAR_TIMESTAMP, resources.getString(R.string.bv_ts)),
};
}
@Override
public void onResume() {
// force an immediate update

View file

@ -17,9 +17,9 @@ import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.script.ScriptExecutor;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher.script.api.Lightning;
import net.pierrox.lightning_launcher.script.api.Property;
import net.pierrox.lightning_launcher.script.api.PropertyEditor;
@ -40,83 +40,32 @@ import java.util.HashMap;
import java.util.HashSet;
public class VariableManager {
private LightningEngine mEngine;
private int mDate;
private HashMap<String,Variable> mVariables;
private HashMap<String, ArrayList<Target>> mVariableTargets;
private HashSet<Variable> mModifiedVariables;
private StringBuilder mTmpStringBuilder = new StringBuilder();
private boolean mUpdatesPaused;
public static Pair<String,? extends Interpolator> DEFAULT_INTERPOLATOR = new Pair<>("ad", new AccelerateDecelerateInterpolator());
private static Pair<String,Interpolator>[] sInterpolators = new Pair[] {
DEFAULT_INTERPOLATOR,
new Pair<>("ac", new AccelerateInterpolator()),
new Pair<>("de", new DecelerateInterpolator()),
new Pair<>("li", new LinearInterpolator()),
new Pair<>("an", new AnticipateInterpolator()),
new Pair<>("as", new AnticipateOvershootInterpolator()),
new Pair<>("bo", new BounceInterpolator()),
new Pair<>("ov", new OvershootInterpolator()),
};
private static class Animator {
Interpolator interpolator;
long start;
long duration;
long offset;
double fromValue;
double toValue;
String name;
String varName;
double lastValue;
int lastValueDate = -1;
boolean done;
private Animator(String var_name, long duration, String interpolator_name, long offset) {
this.name = name(var_name, duration, interpolator_name, offset);
this.varName = var_name;
this.duration = duration;
this.interpolator = getInterpolatorByName(interpolator_name);
this.offset = offset;
}
public void start(double fromValue, double toValue, int date) {
this.fromValue = this.lastValue = fromValue;
this.toValue = toValue;
this.lastValueDate = date;
this.start = AnimationUtils.currentAnimationTimeMillis();
this.done = false;
}
public void setLastValue(double value, int date) {
lastValue = value;
lastValueDate = date;
}
private Interpolator getInterpolatorByName(String interpolator_name) {
for(Pair<String,Interpolator> p : sInterpolators) {
if(p.first.equals(interpolator_name)) {
return p.second;
}
}
return DEFAULT_INTERPOLATOR.second;
}
public static String name(String var_name, long duration, String interpolator, long offset) {
return var_name+duration+interpolator+offset;
}
}
private Handler mHandler;
private ArrayList<Animator> mAnimators;
private boolean mAnimateScheduled;
private File mValuesFile;
private static final String TOK_VARIABLES = "v";
private static final String TOK_NAME = "n";
private static final String TOK_VALUE = "v";
public static Pair<String, ? extends Interpolator> DEFAULT_INTERPOLATOR = new Pair<>("ad", new AccelerateDecelerateInterpolator());
private static final Pair<String, Interpolator>[] sInterpolators = new Pair[]{
DEFAULT_INTERPOLATOR,
new Pair<>("ac", new AccelerateInterpolator()),
new Pair<>("de", new DecelerateInterpolator()),
new Pair<>("li", new LinearInterpolator()),
new Pair<>("an", new AnticipateInterpolator()),
new Pair<>("as", new AnticipateOvershootInterpolator()),
new Pair<>("bo", new BounceInterpolator()),
new Pair<>("ov", new OvershootInterpolator()),
};
private final LightningEngine mEngine;
private final HashMap<String, Variable> mVariables;
private final HashMap<String, ArrayList<Target>> mVariableTargets;
private final StringBuilder mTmpStringBuilder = new StringBuilder();
private final Handler mHandler;
private final ArrayList<Animator> mAnimators;
private final File mValuesFile;
private int mDate;
private HashSet<Variable> mModifiedVariables;
private boolean mUpdatesPaused;
private boolean mAnimateScheduled;
private ArrayList<Target> mTmpModifiedTargets = new ArrayList<>(); // limit allocations
public VariableManager(LightningEngine engine, File load_values_from) {
mEngine = engine;
@ -127,11 +76,11 @@ public class VariableManager {
mValuesFile = load_values_from;
JSONObject values = FileUtils.readJSONObjectFromFile(load_values_from);
if(values != null) {
if (values != null) {
try {
JSONArray jvariables = values.getJSONArray(TOK_VARIABLES);
int l = jvariables.length();
for(int i=0; i<l; i++) {
for (int i = 0; i < l; i++) {
JSONObject jvariable = jvariables.getJSONObject(i);
String name = jvariable.getString(TOK_NAME);
Object value = jvariable.get(TOK_VALUE);
@ -143,11 +92,24 @@ public class VariableManager {
}
}
private static String getIdentifier(String text, int start) {
int pos = start + 1;
int l = text.length();
while (pos < l && isIdentifierChar(text.charAt(pos))) {
pos++;
}
return pos > l ? null : text.substring(start, pos);
}
private static boolean isIdentifierChar(char c) {
return c == '_' || Character.isLetterOrDigit(c);
}
public void saveValues() {
try {
JSONArray jvariables = new JSONArray();
for(Variable variable : getUserVariables()) {
if(variable.value != null) {
for (Variable variable : getUserVariables()) {
if (variable.value != null) {
JSONObject jvariable = new JSONObject();
jvariable.put(TOK_NAME, variable.name);
jvariable.put(TOK_VALUE, variable.value);
@ -157,7 +119,7 @@ public class VariableManager {
JSONObject jdata = new JSONObject();
jdata.put(TOK_VARIABLES, jvariables);
FileUtils.saveStringToFile(jdata.toString(), mValuesFile);
} catch(Exception e) {
} catch (Exception e) {
mValuesFile.delete();
}
}
@ -168,14 +130,14 @@ public class VariableManager {
public void resumeUpdates() {
mUpdatesPaused = false;
if(mModifiedVariables != null && mModifiedVariables.size()>0) {
if (mModifiedVariables != null && mModifiedVariables.size() > 0) {
commit();
}
}
public Variable getVariable(String name) {
Variable var = mVariables.get(name);
if(var == null) {
if (var == null) {
var = new Variable(name, null);
mVariables.put(name, var);
}
@ -188,22 +150,22 @@ public class VariableManager {
public ArrayList<Variable> getUserVariables() {
LLApp llApp = LLApp.get();
Pair<String,BuiltinVariable[]>[] builtin_variables = mEngine.getBuiltinDataCollectors().getBuiltinVariables();
Pair<String, BuiltinVariable[]>[] builtin_variables = mEngine.getBuiltinDataCollectors().getBuiltinVariables();
Collection<Variable> all_variables = getAllVariables();
ArrayList<Variable> user_variables = new ArrayList<>();
for(Variable variable : all_variables) {
for (Variable variable : all_variables) {
boolean found = false;
String name = variable.name;
loop:
for(Pair<String,BuiltinVariable[]> p : builtin_variables) {
for(BuiltinVariable bv : p.second) {
if(bv.name.equals(name)) {
for (Pair<String, BuiltinVariable[]> p : builtin_variables) {
for (BuiltinVariable bv : p.second) {
if (bv.name.equals(name)) {
found = true;
break loop;
}
}
}
if(!found) {
if (!found) {
user_variables.add(variable);
}
}
@ -218,7 +180,7 @@ public class VariableManager {
}
public void edit() {
if(mModifiedVariables == null) {
if (mModifiedVariables == null) {
mModifiedVariables = new HashSet<>();
}
mDate++;
@ -227,10 +189,10 @@ public class VariableManager {
public void setVariable(String name, Object new_value) {
Variable variable = getVariable(name);
Object old_value = variable.value;
if((new_value==null && old_value != null) || (new_value != null && !new_value.equals(old_value))) {
for(int i=mAnimators.size()-1; i>=0; i--) {
if ((new_value == null && old_value != null) || (new_value != null && !new_value.equals(old_value))) {
for (int i = mAnimators.size() - 1; i >= 0; i--) {
Animator animator = mAnimators.get(i);
if(animator.varName.equals(name)) {
if (animator.varName.equals(name)) {
animator.start(animator.done ? Value.asDouble(old_value) : animator.lastValue, Value.asDouble(new_value), mDate);
}
}
@ -248,7 +210,7 @@ public class VariableManager {
boolean animate;
String animator_name = Animator.name(var_name, duration, interpolator, offset);
Animator animator = findAnimator(animator_name);
if(animator == null) {
if (animator == null) {
// prepare an animator but do not run it, it will be activated upon next variable change
double to = Value.asDouble(new_value);
@ -259,12 +221,12 @@ public class VariableManager {
result = to;
animate = false;
} else {
if(animator.lastValueDate == mDate || animator.done) {
if (animator.lastValueDate == mDate || animator.done) {
result = animator.lastValue;
animate = true;
} else {
long delta = AnimationUtils.currentAnimationTimeMillis() - animator.start;
if(delta <= animator.offset) {
if (delta <= animator.offset) {
result = animator.fromValue;
animate = true;
} else {
@ -283,7 +245,7 @@ public class VariableManager {
}
}
}
if(animate && !mAnimateScheduled) {
if (animate && !mAnimateScheduled) {
mAnimateScheduled = true;
mHandler.post(mAnimate);
}
@ -291,32 +253,22 @@ public class VariableManager {
return result;
}
private Animator findAnimator(String name) {
for(Animator a : mAnimators) {
if(name.equals(a.name)) {
return a;
}
}
return null;
}
private Runnable mAnimate = new Runnable() {
private final Runnable mAnimate = new Runnable() {
@Override
public void run() {
edit();
for(Animator a : mAnimators) {
for (Animator a : mAnimators) {
mModifiedVariables.add(getVariable(a.varName));
}
commit();
int done_count = 0;
for(int i=mAnimators.size()-1; i>=0; i--) {
for (int i = mAnimators.size() - 1; i >= 0; i--) {
Animator a = mAnimators.get(i);
if(a.done) {
if (a.done) {
done_count++;
}
}
if(mAnimators.size() > done_count) {
if (mAnimators.size() > done_count) {
mHandler.post(mAnimate);
} else {
mAnimateScheduled = false;
@ -324,10 +276,19 @@ public class VariableManager {
}
};
private ArrayList<Target> mTmpModifiedTargets = new ArrayList<>(); // limit allocations
private Animator findAnimator(String name) {
for (Animator a : mAnimators) {
if (name.equals(a.name)) {
return a;
}
}
return null;
}
public void commit() {
if(!mUpdatesPaused) {
if(mTmpModifiedTargets == null) {
if (!mUpdatesPaused) {
if (mTmpModifiedTargets == null) {
mTmpModifiedTargets = new ArrayList<>();
} else {
mTmpModifiedTargets.clear();
@ -339,7 +300,7 @@ public class VariableManager {
// modifies the item and forces the view to be rebuilt, and as a consequence bindings
// to be rebuilt. This should be safe since the number and order of bindings remain
// the same. It is forbidden to modify bindings in a script triggered by a binding.
for (int i=targets.size()-1; i>=0; i--) {
for (int i = targets.size() - 1; i >= 0; i--) {
Target target = targets.get(i);
if (target.dateComputed != mDate) {
Object old_value = target.value;
@ -362,20 +323,28 @@ public class VariableManager {
// TODO sort targets per page/item in order to group properties changes
ScriptExecutor se = mEngine.getScriptExecutor();
Lightning ll = se.getLightning();
for(Target target : targets) {
for (Target target : targets) {
PropertySet ps = ll.getCachedItem(target.itemView).getProperties();
Object value = target.value;
if(value != null) {
if (value != null) {
String field = target.field;
PropertyEditor editor = ps.edit();
try {
switch(Property.getType(field)) {
case Property.TYPE_BOOLEAN: editor.setBoolean(field, Value.asBoolean(value)); break;
case Property.TYPE_INTEGER: editor.setInteger(field, Value.asInteger(value)); break;
case Property.TYPE_FLOAT: editor.setFloat(field, Value.asFloat(value)); break;
case Property.TYPE_STRING: editor.setString(field, Value.asString(value)); break;
switch (Property.getType(field)) {
case Property.TYPE_BOOLEAN:
editor.setBoolean(field, Value.asBoolean(value));
break;
case Property.TYPE_INTEGER:
editor.setInteger(field, Value.asInteger(value));
break;
case Property.TYPE_FLOAT:
editor.setFloat(field, Value.asFloat(value));
break;
case Property.TYPE_STRING:
editor.setString(field, Value.asString(value));
break;
}
} catch(RhinoException e) {
} catch (RhinoException e) {
se.displayScriptError(e);
return;
}
@ -384,17 +353,17 @@ public class VariableManager {
}
}
public Pair<String,String[]> convertFormulaToScript(String formula) {
public Pair<String, String[]> convertFormulaToScript(String formula) {
int formula_length = formula.length();
// decode variable names
HashSet<String> names = new HashSet<>();
int p = -1;
while((p = formula.indexOf('$', p+1)) != -1) {
while ((p = formula.indexOf('$', p + 1)) != -1) {
p++;
if(p < formula_length && isIdentifierChar(formula.charAt(p))) {
if (p < formula_length && isIdentifierChar(formula.charAt(p))) {
String identifier = getIdentifier(formula, p);
if(identifier != null) {
if (identifier != null) {
names.add(identifier);
}
}
@ -404,14 +373,14 @@ public class VariableManager {
names.toArray(variable_names);
mTmpStringBuilder.setLength(0);
if(!formula.contains("return")) {
if (!formula.contains("return")) {
mTmpStringBuilder.append("return ");
}
for(p=0; p<formula_length; p++) {
for (p = 0; p < formula_length; p++) {
char c = formula.charAt(p);
if(c == '$') {
if (c == '$') {
p++;
if(p == formula_length) {
if (p == formula_length) {
break;
}
c = formula.charAt(p);
@ -424,7 +393,7 @@ public class VariableManager {
public void updateBindings(ItemView itemView, Binding[] bindings, boolean apply, Screen fromScreen, boolean removeOldTargets) {
// remove old targets
if(removeOldTargets) {
if (removeOldTargets) {
ScriptManager sm = mEngine.getScriptManager();
for (ArrayList<Target> targets : mVariableTargets.values()) {
for (int l = targets.size() - 1; l >= 0; l--) {
@ -439,26 +408,26 @@ public class VariableManager {
}
}
if(bindings == null) {
if (bindings == null) {
return;
}
// add new one
ScriptManager sm = mEngine.getScriptManager();
ArrayList<Target> targets = new ArrayList<>(bindings.length);
for(Binding binding : bindings) {
if(!binding.enabled) {
for (Binding binding : bindings) {
if (!binding.enabled) {
continue;
}
final String formula = binding.formula;
int formula_length = formula.length();
if(formula_length == 0) {
if (formula_length == 0) {
continue;
}
final String field = binding.target;
if(field == null || field.length() == 0) {
if (field == null || field.length() == 0) {
continue;
}
@ -473,7 +442,7 @@ public class VariableManager {
}
if (simple_identifier == null) {
// this is a function, convert it to a script and extract variable names
Pair<String,String[]> p = convertFormulaToScript(formula);
Pair<String, String[]> p = convertFormulaToScript(formula);
// create a script from this
Script script = sm.createScriptForBinding(itemView, binding);
@ -485,14 +454,14 @@ public class VariableManager {
target = addTarget(itemView, field, new String[]{simple_identifier}, null);
}
if(apply) {
if (apply) {
computeTarget(target, fromScreen);
targets.add(target);
}
}
// apply new values
if(apply) {
if (apply) {
applyTargets(targets);
}
}
@ -500,34 +469,21 @@ public class VariableManager {
private Target addTarget(ItemView itemView, String field, String[] variable_names, Script script) {
int l = variable_names.length;
Variable[] variables = new Variable[l];
for(int i=0; i<l; i++) {
for (int i = 0; i < l; i++) {
variables[i] = getVariable(variable_names[i]);
}
Target target = new Target(itemView, field, variables, script);
for(Variable v : variables) {
for (Variable v : variables) {
getTargetsForVariable(v.name).add(target);
}
return target;
}
private static String getIdentifier(String text, int start) {
int pos = start+1;
int l = text.length();
while(pos < l && isIdentifierChar(text.charAt(pos))) {
pos++;
}
return pos > l ? null : text.substring(start, pos);
}
private static boolean isIdentifierChar(char c) {
return c=='_' || Character.isLetterOrDigit(c);
}
private ArrayList<Target> getTargetsForVariable(String name) {
ArrayList<Target> targets = mVariableTargets.get(name);
if(targets == null) {
if (targets == null) {
targets = new ArrayList<>();
mVariableTargets.put(name, targets);
}
@ -535,31 +491,82 @@ public class VariableManager {
}
private void computeTarget(Target target, Screen fromScreen) {
if(target.script == null) {
if (target.script == null) {
target.value = target.variables[0].value;
} else {
int l = target.variables.length;
Object[] arguments = new Object[l+2];
Object[] arguments = new Object[l + 2];
mTmpStringBuilder.setLength(0);
mTmpStringBuilder.append("item,target");
// TODO not sure whether this is really efficient, can it be optimized?
ScriptExecutor se = mEngine.getScriptExecutor();
Lightning ll = se.getLightning();
arguments[0] = ll.getCachedItem(target.itemView);
arguments[1] = target.field;
arguments[0] = ll.getCachedItem(target.itemView);
arguments[1] = target.field;
for(int i=0; i<l; i++) {
for (int i = 0; i < l; i++) {
Variable variable = target.variables[i];
arguments[i+2] = variable.value;
arguments[i + 2] = variable.value;
mTmpStringBuilder.append(',');
mTmpStringBuilder.append(variable.name);
}
Object result = se.runScriptAsFunction(fromScreen, target.script.id, mTmpStringBuilder.toString(), arguments, false, true);
if(result != null) {
if (result != null) {
target.value = result;
}
}
target.dateComputed = mDate;
}
private static class Animator {
Interpolator interpolator;
long start;
long duration;
long offset;
double fromValue;
double toValue;
String name;
String varName;
double lastValue;
int lastValueDate = -1;
boolean done;
private Animator(String var_name, long duration, String interpolator_name, long offset) {
this.name = name(var_name, duration, interpolator_name, offset);
this.varName = var_name;
this.duration = duration;
this.interpolator = getInterpolatorByName(interpolator_name);
this.offset = offset;
}
public static String name(String var_name, long duration, String interpolator, long offset) {
return var_name + duration + interpolator + offset;
}
public void start(double fromValue, double toValue, int date) {
this.fromValue = this.lastValue = fromValue;
this.toValue = toValue;
this.lastValueDate = date;
this.start = AnimationUtils.currentAnimationTimeMillis();
this.done = false;
}
public void setLastValue(double value, int date) {
lastValue = value;
lastValueDate = date;
}
private Interpolator getInterpolatorByName(String interpolator_name) {
for (Pair<String, Interpolator> p : sInterpolators) {
if (p.first.equals(interpolator_name)) {
return p.second;
}
}
return DEFAULT_INTERPOLATOR.second;
}
}
}

View file

@ -12,9 +12,7 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.util.DisplayMetrics;
@ -114,7 +112,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
lightningEngine.registerGlobalConfigChangeListener(this);
final GlobalConfig globalConfig = lightningEngine.getGlobalConfig();
mOverlayScreen = globalConfig.overlayScreen;
mOverlayShowHandlePosition =globalConfig.overlayShowHandlePosition;
mOverlayShowHandlePosition = globalConfig.overlayShowHandlePosition;
mOverlayShowHandleSize = globalConfig.overlayShowHandleSize;
mOverlayShowHandleWidth = globalConfig.overlayShowHandleWidth;
mOverlayHideHandlePosition = globalConfig.overlayHideHandlePosition;
@ -131,7 +129,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
public boolean onKey(View v, int keyCode, KeyEvent event) {
int action = event.getAction();
if (keyCode == KeyEvent.KEYCODE_MENU) {
if(action == KeyEvent.ACTION_UP) {
if (action == KeyEvent.ACTION_UP) {
EventAction ea = mMainPage.config.menuKey;
if (ea.action == GlobalConfig.UNSET) {
ea = globalConfig.menuKey;
@ -140,13 +138,13 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
if(action == KeyEvent.ACTION_UP) {
if (action == KeyEvent.ACTION_UP) {
FolderView fv = mScreen.findTopmostFolderView();
if (fv != null) {
mScreen.closeFolder(fv, true);
} else {
EventAction ea = mMainPage.config.backKey;
if(ea.action == GlobalConfig.UNSET) {
if (ea.action == GlobalConfig.UNSET) {
hideWorkspace();
} else {
mScreen.runAction(mMainPage.getEngine(), "K_BACK", ea);
@ -172,12 +170,12 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mHideHandle = mContentView.findViewById(R.id.hide_handle);
mHideHandle.setVisibility(View.GONE);
mItemLayout=(ItemLayout) mWorkspaceView.findViewById(R.id.window_il);
mItemLayout = mWorkspaceView.findViewById(R.id.window_il);
mScreen.takeItemLayoutOwnership(mItemLayout);
mItemLayout.setHonourFocusChange(false);
int windowType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,
@ -186,10 +184,10 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
// |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
// |WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
// |WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE
|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|0,
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| 0,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.LEFT | Gravity.TOP;
// mWindowManager.addView(mContentView, lp);
@ -200,7 +198,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
Class PolicyManager = getClass().getClassLoader().loadClass("com.android.internal.policy.PolicyManager");
Method m = PolicyManager.getMethod("makeNewWindow", Context.class);
mWindow = (Window) m.invoke(null, this);
} catch(ClassNotFoundException e) {
} catch (ClassNotFoundException e) {
// starting at Android 6
Class PhoneWindow = getClass().getClassLoader().loadClass("com.android.internal.policy.PhoneWindow");
mWindow = (Window) PhoneWindow.getDeclaredConstructor(Context.class).newInstance(this);
@ -380,7 +378,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null) {
if (intent != null) {
String action = intent.getAction();
if (INTENT_ACTION_SHOW.equals(action)) {
showWorkspace();
@ -394,7 +392,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override
public final Resources getResources() {
if(mResourcesWrapperHelper == null) {
if (mResourcesWrapperHelper == null) {
mResourcesWrapperHelper = new ResourcesWrapperHelper(this, super.getResources());
}
return mResourcesWrapperHelper.getResources();
@ -416,12 +414,12 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override
public void onGlobalConfigChanged(GlobalConfig newGlobalConfig) {
if(newGlobalConfig.overlayScreen != mOverlayScreen) {
if (newGlobalConfig.overlayScreen != mOverlayScreen) {
mOverlayScreen = newGlobalConfig.overlayScreen;
configurePage();
}
if(newGlobalConfig.overlayAnimation != mOverlayAnimation ||
if (newGlobalConfig.overlayAnimation != mOverlayAnimation ||
newGlobalConfig.overlayShowHandlePosition != mOverlayShowHandlePosition ||
newGlobalConfig.overlayShowHandleSize != mOverlayShowHandleSize ||
newGlobalConfig.overlayShowHandleWidth != mOverlayShowHandleWidth ||
@ -546,8 +544,8 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mShowHandle.setBackgroundColor(mOverlayDisplayHandles ? 0x8000a000 : 0);
mHideHandle.setBackgroundColor(mOverlayDisplayHandles ? 0x80a00000 : 0);
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams)mWindow.getDecorView().getLayoutParams());
lp.gravity = ((FrameLayout.LayoutParams)mShowHandle.getLayoutParams()).gravity;
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams) mWindow.getDecorView().getLayoutParams());
lp.gravity = ((FrameLayout.LayoutParams) mShowHandle.getLayoutParams()).gravity;
mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
// mWindow.setGravity(((FrameLayout.LayoutParams)mShowHandle.getLayoutParams()).gravity);
@ -827,20 +825,28 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mWorkspaceView.setTranslationX(0);
mWorkspaceView.setTranslationY(0);
if(mOverlayAnimation == GlobalConfig.OverlayAnimation.SLIDE) {
if (mOverlayAnimation == GlobalConfig.OverlayAnimation.SLIDE) {
boolean visible = mWorkspaceView.getVisibility() == View.VISIBLE;
switch (mOverlayShowHandlePosition) {
// FIXME I don't understand why X and Y are inverted, as if not everything was rotated at this time
case LEFT_TOP: case LEFT_MIDDLE: case LEFT_BOTTOM:
case LEFT_TOP:
case LEFT_MIDDLE:
case LEFT_BOTTOM:
mWorkspaceView.setTranslationX(visible ? 0 : -mScreenWidth);
break;
case RIGHT_TOP: case RIGHT_MIDDLE: case RIGHT_BOTTOM:
case RIGHT_TOP:
case RIGHT_MIDDLE:
case RIGHT_BOTTOM:
mWorkspaceView.setTranslationX(visible ? 0 : mScreenWidth);
break;
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT:
case TOP_LEFT:
case TOP_CENTER:
case TOP_RIGHT:
mWorkspaceView.setTranslationY(visible ? 0 : -mScreenHeight);
break;
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT:
case BOTTOM_LEFT:
case BOTTOM_CENTER:
case BOTTOM_RIGHT:
mWorkspaceView.setTranslationY(visible ? 0 : mScreenHeight);
break;
}
@ -849,42 +855,58 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
private ViewPropertyAnimator createDrawerAnimation(GlobalConfig.OverlayHandlePosition from, boolean show, long duration) {
ViewPropertyAnimator animator = mWorkspaceView.animate();
if(show) {
if(mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) {
if (show) {
if (mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) {
animator.alpha(1);
} else {
switch (from) {
case LEFT_TOP: case LEFT_MIDDLE: case LEFT_BOTTOM:
case RIGHT_TOP: case RIGHT_MIDDLE: case RIGHT_BOTTOM:
case LEFT_TOP:
case LEFT_MIDDLE:
case LEFT_BOTTOM:
case RIGHT_TOP:
case RIGHT_MIDDLE:
case RIGHT_BOTTOM:
animator.translationX(0);
break;
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT:
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT:
case TOP_LEFT:
case TOP_CENTER:
case TOP_RIGHT:
case BOTTOM_LEFT:
case BOTTOM_CENTER:
case BOTTOM_RIGHT:
animator.translationY(0);
break;
}
}
} else {
if(mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) {
if (mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) {
animator.alpha(0);
} else {
boolean is_show_handle = from == mOverlayShowHandlePosition;
switch (from) {
case LEFT_TOP: case LEFT_MIDDLE: case LEFT_BOTTOM:
animator.translationX(is_show_handle ? -mScreenWidth-1 : mScreenWidth+1);
case LEFT_TOP:
case LEFT_MIDDLE:
case LEFT_BOTTOM:
animator.translationX(is_show_handle ? -mScreenWidth - 1 : mScreenWidth + 1);
break;
case RIGHT_TOP: case RIGHT_MIDDLE: case RIGHT_BOTTOM:
animator.translationX(is_show_handle ? mScreenWidth+1 : -mScreenWidth-1);
case RIGHT_TOP:
case RIGHT_MIDDLE:
case RIGHT_BOTTOM:
animator.translationX(is_show_handle ? mScreenWidth + 1 : -mScreenWidth - 1);
break;
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT:
animator.translationY(is_show_handle ? -mScreenHeight-1 : mScreenHeight+1);
case TOP_LEFT:
case TOP_CENTER:
case TOP_RIGHT:
animator.translationY(is_show_handle ? -mScreenHeight - 1 : mScreenHeight + 1);
break;
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT:
animator.translationY(is_show_handle ? mScreenHeight+1 : -mScreenHeight-1);
case BOTTOM_LEFT:
case BOTTOM_CENTER:
case BOTTOM_RIGHT:
animator.translationY(is_show_handle ? mScreenHeight + 1 : -mScreenHeight - 1);
break;
}
}
@ -922,7 +944,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
public void onAnimationEnd(Animator animator) {
mWorkspaceView.setTranslationX(0);
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams)mWindow.getDecorView().getLayoutParams());
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams) mWindow.getDecorView().getLayoutParams());
lp.flags = 0;
mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
@ -955,7 +977,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mShowHandle.setVisibility(View.VISIBLE);
mHideHandle.setVisibility(View.GONE);
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams)mWindow.getDecorView().getLayoutParams());
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams) mWindow.getDecorView().getLayoutParams());
lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
@ -975,14 +997,14 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
}
protected void showWorkspace() {
if(!mIsShown) {
if (!mIsShown) {
overlayIsShown();
showWorkspace(mOverlayShowHandlePosition, true, OPEN_CLOSE_ANIMATION_DURATION);
}
}
protected void hideWorkspace() {
if(mIsShown) {
if (mIsShown) {
overlayIsHidden();
hideWorkspace(mOverlayHideHandlePosition, true, OPEN_CLOSE_ANIMATION_DURATION);
}
@ -1005,7 +1027,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override
public ItemLayout loadRootItemLayout(int page, boolean reset_navigation_history, boolean displayImmediately, boolean animate) {
if(mItemLayout.getPage().id == page) {
if (mItemLayout.getPage().id == page) {
return mItemLayout;
} else {
return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate);
@ -1020,7 +1042,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override
protected void launchIntent(Intent intent, ItemView itemView) {
super.launchIntent(intent, itemView);
if(LLApp.get().getAppEngine().getGlobalConfig().overlayLaunchHide) {
if (LLApp.get().getAppEngine().getGlobalConfig().overlayLaunchHide) {
hideWorkspace();
}

View file

@ -18,21 +18,17 @@ import net.pierrox.lightning_launcher.R;
import java.text.DecimalFormat;
public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSeekBarChangeListener, View.OnClickListener, DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
public interface OnDialogPreferenceSliderListener {
public void onDialogPreferenceSliderValueSet(float value);
public void onDialogPreferenceSliderCancel();
}
private boolean mIsFloat;
private float mMinValue;
private float mMaxValue;
private float mInterval;
private String mUnit;
private static final DecimalFormat sFloatFormat0 = new DecimalFormat("0.#");
private static final DecimalFormat sFloatFormat1 = new DecimalFormat("0.0");
private final boolean mIsFloat;
private final float mMinValue;
private final float mMaxValue;
private final float mInterval;
private final String mUnit;
private final OnDialogPreferenceSliderListener mListener;
private SeekBar mDialogSeekBar;
private EditText mDialogEditText;
private float mDialogValue;
private OnDialogPreferenceSliderListener mListener;
public DialogPreferenceSlider(Context context, float value, boolean is_float, float min, float max, float interval, String unit, OnDialogPreferenceSliderListener listener) {
super(context);
@ -46,6 +42,22 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
mListener = listener;
}
/*package*/
static String valueAsText(boolean is_float, String unit, float value, float interval) {
String text;
if (is_float) {
if (unit != null && unit.equals("%")) {
text = String.valueOf(Math.round(value * 100));
} else {
DecimalFormat format = interval < 1 ? sFloatFormat1 : sFloatFormat0;
text = format.format(value);
}
} else {
text = String.valueOf(Math.round(value));
}
return text;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@ -54,15 +66,15 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
view.findViewById(R.id.minus).setOnClickListener(this);
view.findViewById(R.id.plus).setOnClickListener(this);
mDialogSeekBar = (SeekBar) view.findViewById(R.id.seek_bar);
mDialogSeekBar.setMax((int)((mMaxValue - mMinValue)/mInterval));
mDialogSeekBar = view.findViewById(R.id.seek_bar);
mDialogSeekBar.setMax((int) ((mMaxValue - mMinValue) / mInterval));
mDialogSeekBar.setProgress(getProgressForValue(mDialogValue));
mDialogSeekBar.setOnSeekBarChangeListener(this);
mDialogEditText = (EditText) view.findViewById(R.id.value);
if(mIsFloat) {
mDialogEditText = view.findViewById(R.id.value);
if (mIsFloat) {
mDialogEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | (mMinValue < 0 ? InputType.TYPE_NUMBER_FLAG_SIGNED : InputType.TYPE_NUMBER_VARIATION_NORMAL));
} else {
mDialogEditText.setInputType(InputType.TYPE_CLASS_NUMBER | (mMinValue<0 ? InputType.TYPE_NUMBER_FLAG_SIGNED : InputType.TYPE_NUMBER_VARIATION_NORMAL));
mDialogEditText.setInputType(InputType.TYPE_CLASS_NUMBER | (mMinValue < 0 ? InputType.TYPE_NUMBER_FLAG_SIGNED : InputType.TYPE_NUMBER_VARIATION_NORMAL));
}
String value = valueAsText(mIsFloat, mUnit, mDialogValue, mInterval);
mDialogEditText.setText(value);
@ -75,26 +87,26 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
int after) {
// pass
}
@Override
public void afterTextChanged(Editable s) {
try {
float value=Float.parseFloat(s.toString().replace(',', '.'));
if("%".equals(mUnit)) {
value/=100;
float value = Float.parseFloat(s.toString().replace(',', '.'));
if ("%".equals(mUnit)) {
value /= 100;
}
mDialogSeekBar.setProgress(getProgressForValue(value));
mDialogValue = value;
} catch(NumberFormatException e) {
} catch (NumberFormatException e) {
// pass
}
}
});
TextView unitv = (TextView) view.findViewById(R.id.unit);
TextView unitv = view.findViewById(R.id.unit);
unitv.setText(mUnit);
setView(view);
@ -106,15 +118,14 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
super.onCreate(savedInstanceState);
}
@Override
public void onClick(View v) {
if(v.getId()==R.id.minus) {
mDialogValue-=mInterval;
if(mDialogValue<mMinValue) mDialogValue=mMinValue;
if (v.getId() == R.id.minus) {
mDialogValue -= mInterval;
if (mDialogValue < mMinValue) mDialogValue = mMinValue;
} else {
mDialogValue+=mInterval;
if(mDialogValue>mMaxValue) mDialogValue=mMaxValue;
mDialogValue += mInterval;
if (mDialogValue > mMaxValue) mDialogValue = mMaxValue;
}
String value = valueAsText(mIsFloat, mUnit, mDialogValue, mInterval);
mDialogEditText.setText(value);
@ -124,13 +135,13 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
@Override
public void onClick(DialogInterface dialog, int which) {
switch(which) {
case BUTTON_POSITIVE:
mListener.onDialogPreferenceSliderValueSet(mDialogValue);
break;
case BUTTON_NEGATIVE:
mListener.onDialogPreferenceSliderCancel();
break;
switch (which) {
case BUTTON_POSITIVE:
mListener.onDialogPreferenceSliderValueSet(mDialogValue);
break;
case BUTTON_NEGATIVE:
mListener.onDialogPreferenceSliderCancel();
break;
}
}
@ -141,7 +152,7 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser) {
if (fromUser) {
String value = valueAsText(mIsFloat, mUnit, getValueForCurrentProgress(), mInterval);
mDialogEditText.setText(value);
mDialogEditText.setSelection(value.length());
@ -159,27 +170,16 @@ public class DialogPreferenceSlider extends AlertDialog implements SeekBar.OnSee
}
private float getValueForCurrentProgress() {
return mDialogSeekBar.getProgress()*(mMaxValue-mMinValue)/mDialogSeekBar.getMax()+mMinValue;
return mDialogSeekBar.getProgress() * (mMaxValue - mMinValue) / mDialogSeekBar.getMax() + mMinValue;
}
private int getProgressForValue(float value) {
return (int)((value-mMinValue)/(mMaxValue-mMinValue)*mDialogSeekBar.getMax());
return (int) ((value - mMinValue) / (mMaxValue - mMinValue) * mDialogSeekBar.getMax());
}
private static DecimalFormat sFloatFormat0 = new DecimalFormat("0.#");
private static DecimalFormat sFloatFormat1 = new DecimalFormat("0.0");
/*package*/ static String valueAsText(boolean is_float, String unit, float value, float interval) {
String text;
if (is_float) {
if(unit!=null && unit.equals("%")) {
text=String.valueOf(Math.round(value*100));
} else {
DecimalFormat format=interval<1 ? sFloatFormat1 : sFloatFormat0;
text=format.format(value);
}
} else {
text=String.valueOf(Math.round(value));
}
return text;
public interface OnDialogPreferenceSliderListener {
void onDialogPreferenceSliderValueSet(float value);
void onDialogPreferenceSliderCancel();
}
}

Some files were not shown because too many files have changed in this diff Show more