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.Base64;
import com.google.android.vending.licensing.util.Base64DecoderException; import com.google.android.vending.licensing.util.Base64DecoderException;
import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.spec.KeySpec; 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 KEYGEN_ALGORITHM = "PBEWITHSHAAND256BITAES-CBC-BC";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final byte[] IV = 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 static final String header = "com.android.vending.licensing.AESObfuscator-1|";
private Cipher mEncryptor; private final Cipher mEncryptor;
private Cipher mDecryptor; 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 applicationId application identifier, e.g. the package name
* @param deviceId device identifier. Use as many sources as possible to * @param deviceId device identifier. Use as many sources as possible to
* create this unique identifier. * create this unique identifier.
*/ */
public AESObfuscator(byte[] salt, String applicationId, String deviceId) { public AESObfuscator(byte[] salt, String applicationId, String deviceId) {
try { try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEYGEN_ALGORITHM); SecretKeyFactory factory = SecretKeyFactory.getInstance(KEYGEN_ALGORITHM);
KeySpec keySpec = KeySpec keySpec =
new PBEKeySpec((applicationId + deviceId).toCharArray(), salt, 1024, 256); new PBEKeySpec((applicationId + deviceId).toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(keySpec); SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
mEncryptor = Cipher.getInstance(CIPHER_ALGORITHM); mEncryptor = Cipher.getInstance(CIPHER_ALGORITHM);
@ -75,9 +75,7 @@ public class AESObfuscator implements Obfuscator {
} }
try { try {
// Header is appended as an integrity check // Header is appended as an integrity check
return Base64.encode(mEncryptor.doFinal((header + key + original).getBytes(UTF8))); return Base64.encode(mEncryptor.doFinal((header + key + original).getBytes(StandardCharsets.UTF_8)));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Invalid environment", e);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException("Invalid environment", e); throw new RuntimeException("Invalid environment", e);
} }
@ -88,23 +86,21 @@ public class AESObfuscator implements Obfuscator {
return null; return null;
} }
try { 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 // Check for presence of header. This serves as a final integrity check, for cases
// where the block size is correct during decryption. // where the block size is correct during decryption.
int headerIndex = result.indexOf(header+key); int headerIndex = result.indexOf(header + key);
if (headerIndex != 0) { if (headerIndex != 0) {
throw new ValidationException("Header not found (invalid data or key)" + ":" + throw new ValidationException("Header not found (invalid data or key)" + ":" +
obfuscated); obfuscated);
} }
return result.substring(header.length()+key.length(), result.length()); return result.substring(header.length() + key.length());
} catch (Base64DecoderException e) { } catch (Base64DecoderException e) {
throw new ValidationException(e.getMessage() + ":" + obfuscated); throw new ValidationException(e.getMessage() + ":" + obfuscated);
} catch (IllegalBlockSizeException e) { } catch (IllegalBlockSizeException e) {
throw new ValidationException(e.getMessage() + ":" + obfuscated); throw new ValidationException(e.getMessage() + ":" + obfuscated);
} catch (BadPaddingException e) { } catch (BadPaddingException e) {
throw new ValidationException(e.getMessage() + ":" + obfuscated); 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; package com.google.android.vending.licensing;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log;
import net.pierrox.lightning_launcher.data.FileUtils; import net.pierrox.lightning_launcher.data.FileUtils;
@ -32,15 +30,15 @@ import java.io.IOException;
public class JSONDataObfuscator { 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, 42, 13, 27, -7, 1, 63, -51, 94, 107, 120, 4,
-54, -77, 123, -12, -72, -99, 10, 0, 73 -54, -77, 123, -12, -72, -99, 10, 0, 73
}; };
private File mFile; private final File mFile;
private String mPackageName; private final String mPackageName;
private JSONObject mData;
private final Obfuscator mObfuscator; private final Obfuscator mObfuscator;
private JSONObject mData;
public JSONDataObfuscator(Context context) { public JSONDataObfuscator(Context context) {
@ -49,10 +47,10 @@ public class JSONDataObfuscator {
mFile = new File(context.getCacheDir(), "icon"); mFile = new File(context.getCacheDir(), "icon");
mObfuscator = new AESObfuscator(SALT, mPackageName, deviceId); mObfuscator = new AESObfuscator(SALT, mPackageName, deviceId);
String obfuscated_data = FileUtils.readFileContent(mFile); String obfuscated_data = FileUtils.readFileContent(mFile);
if(obfuscated_data != null) { if (obfuscated_data != null) {
try { try {
String data = mObfuscator.unobfuscate(obfuscated_data, context.getPackageName()); String data = mObfuscator.unobfuscate(obfuscated_data, context.getPackageName());
if(data != null) { if (data != null) {
mData = new JSONObject(data); mData = new JSONObject(data);
} }
} catch (Exception e) { } catch (Exception e) {
@ -60,7 +58,7 @@ public class JSONDataObfuscator {
} }
} }
if(mData == null) { if (mData == null) {
mData = new JSONObject(); mData = new JSONObject();
} }
} }

View file

@ -16,11 +16,6 @@
package com.google.android.vending.licensing; 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.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -31,6 +26,11 @@ import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; 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.KeyFactory;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.PublicKey; import java.security.PublicKey;
@ -64,25 +64,23 @@ public class LicenseChecker implements ServiceConnection {
private static final SecureRandom RANDOM = new SecureRandom(); private static final SecureRandom RANDOM = new SecureRandom();
private static final boolean DEBUG_LICENSE_ERROR = false; private static final boolean DEBUG_LICENSE_ERROR = false;
private final PublicKey mPublicKey;
private ILicensingService mService;
private PublicKey mPublicKey;
private final Context mContext; private final Context mContext;
private final Policy mPolicy; private final Policy mPolicy;
/** /**
* A handler for running tasks on a background thread. We don't want license * A handler for running tasks on a background thread. We don't want license
* processing to block the UI thread. * processing to block the UI thread.
*/ */
private Handler mHandler; private final Handler mHandler;
private final String mPackageName; private final String mPackageName;
private final String mVersionCode; private final String mVersionCode;
private final Set<LicenseValidator> mChecksInProgress = new HashSet<LicenseValidator>(); private final Set<LicenseValidator> mChecksInProgress = new HashSet<LicenseValidator>();
private final Queue<LicenseValidator> mPendingChecks = new LinkedList<LicenseValidator>(); private final Queue<LicenseValidator> mPendingChecks = new LinkedList<LicenseValidator>();
private ILicensingService mService;
/** /**
* @param context a Context * @param context a Context
* @param policy implementation of Policy * @param policy implementation of Policy
* @param encodedPublicKey Base64-encoded RSA public key * @param encodedPublicKey Base64-encoded RSA public key
* @throws IllegalArgumentException if encodedPublicKey is invalid * @throws IllegalArgumentException if encodedPublicKey is invalid
*/ */
@ -100,7 +98,7 @@ public class LicenseChecker implements ServiceConnection {
/** /**
* Generates a PublicKey instance from a string containing the * Generates a PublicKey instance from a string containing the
* Base64-encoded public key. * Base64-encoded public key.
* *
* @param encodedPublicKey Base64-encoded public key * @param encodedPublicKey Base64-encoded public key
* @throws IllegalArgumentException if encodedPublicKey is invalid * @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. * Checks if the user should have access to the app. Binds the service if necessary.
* <p> * <p>
@ -131,6 +146,7 @@ public class LicenseChecker implements ServiceConnection {
* <p> * <p>
* source string: "com.android.vending.licensing.ILicensingService" * source string: "com.android.vending.licensing.ILicensingService"
* <p> * <p>
*
* @param callback * @param callback
*/ */
public synchronized void checkAccess(LicenseCheckerCallback callback) { public synchronized void checkAccess(LicenseCheckerCallback callback) {
@ -145,8 +161,8 @@ public class LicenseChecker implements ServiceConnection {
if (mService == null) { if (mService == null) {
// Log.i(TAG, "Binding to licensing service."); // Log.i(TAG, "Binding to licensing service.");
try { try {
String two = String.valueOf((new Date().getYear()+1900)/1000); 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="))); Intent serviceIntent = new Intent(new String(Base64.decode("Y" + two + "9tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY" + two + "Vuc" + two + "luZ1NlcnZpY" + two + "U=")));
serviceIntent.setPackage("com.android.vending"); serviceIntent.setPackage("com.android.vending");
boolean bindResult = mContext boolean bindResult = mContext
.bindService( .bindService(
@ -195,10 +211,88 @@ public class LicenseChecker implements ServiceConnection {
} }
} }
private class ResultListener extends ILicenseResultListener.Stub { public synchronized void onServiceConnected(ComponentName name, IBinder service) {
private final LicenseValidator mValidator; mService = ILicensingService.Stub.asInterface(service);
private Runnable mOnTimeout; 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) { public ResultListener(LicenseValidator validator) {
mValidator = validator; mValidator = validator;
mOnTimeout = new Runnable() { mOnTimeout = new Runnable() {
@ -211,14 +305,10 @@ public class LicenseChecker implements ServiceConnection {
startTimeout(); 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 // Runs in IPC thread pool. Post it to the Handler, so we can guarantee
// either this or the timeout runs. // either this or the timeout runs.
public void verifyLicense(final int responseCode, final String signedData, public void verifyLicense(final int responseCode, final String signedData,
final String signature) { final String signature) {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
public void run() { public void run() {
// Log.i(TAG, "Received response."); // Log.i(TAG, "Received response.");
@ -272,93 +362,4 @@ public class LicenseChecker implements ServiceConnection {
mHandler.removeCallbacks(mOnTimeout); 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 { public interface LicenseCheckerCallback {
/** /**
* Allow use. App should proceed as normal. * Application error codes.
*
* @param reason Policy.LICENSED or Policy.RETRY typically. (although in
* theory the policy can return Policy.NOT_LICENSED here as well)
*/ */
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. * Don't allow use. App should inform user and take appropriate action.
* *
* @param reason Policy.NOT_LICENSED or Policy.RETRY. (although in theory * @param reason Policy.NOT_LICENSED or Policy.RETRY. (although in theory
* the policy can return Policy.LICENSED here as well --- * the policy can return Policy.LICENSED here as well ---
* perhaps the call to the LVL took too long, for example) * perhaps the call to the LVL took too long, for example)
*/ */
public void dontAllow(int reason); 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;
/** /**
* Error in application code. Caller did not call or set up license checker * Error in application code. Caller did not call or set up license checker
* correctly. Should be considered fatal. * 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 * 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 * NOT_LICENSED means that the server returned back a valid license response
* that indicated that the user definitively is not licensed * 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 --- * RETRY means that the license response was unable to be determined ---
* perhaps as a result of faulty networking * 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 * 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 * Provide results from contact with the license server. Retry counts are
* incremented if the current value of response is RETRY. Results will be * incremented if the current value of response is RETRY. Results will be
* used for any future policy decisions. * used for any future policy decisions.
* *
* @param response the result from validating the server response * @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); void processServerResponse(int response, ResponseData rawData);

View file

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

View file

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

View file

@ -33,7 +33,6 @@ import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Handler;
import android.os.Process; import android.os.Process;
import android.view.View; import android.view.View;
import android.widget.Toast; 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.Policy;
import com.google.android.vending.licensing.ServerManagedPolicy; 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.FileUtils;
import net.pierrox.lightning_launcher.data.Page; 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.IabHelper;
import net.pierrox.lightning_launcher.iab.IabResult; import net.pierrox.lightning_launcher.iab.IabResult;
import net.pierrox.lightning_launcher.iab.Inventory; import net.pierrox.lightning_launcher.iab.Inventory;
import net.pierrox.lightning_launcher.iab.Purchase; import net.pierrox.lightning_launcher.iab.Purchase;
import net.pierrox.lightning_launcher.prefs.LLPreference; import net.pierrox.lightning_launcher.prefs.LLPreference;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -67,11 +66,12 @@ public class LLAppExtreme extends LLAppPhone {
private static final String key4 = "hI3T9SPxlX4faIxSX0hwLJAtbb5IZWX5XvuQdQovF9W9"; private static final String key4 = "hI3T9SPxlX4faIxSX0hwLJAtbb5IZWX5XvuQdQovF9W9";
private static final String key5 = "vRdURFT6D7K01k+doWbMDZnbfQXiYKHaaBja+SlsZA4UsHF6RubVTi+nOET1xBlpjNwQ6wl69GdM+y8WA1WR47JBNph6wuCF0q7pz2KbuBDvh5vSvYaBGb9dflqnOKy2S47DSA7HOwffTUtxilskp"; 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 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 LicenseCheckerCallback mLicenseCheckerCallback;
private LicenseChecker mChecker; private LicenseChecker mChecker;
private boolean mIsLicensed = true; private boolean mIsLicensed = true;
private IabHelper mIABHelper; private IabHelper mIABHelper;
private String mIabKey; private String mIabKey;
private boolean mHasLWPIab; private boolean mHasLWPIab;
@ -80,12 +80,12 @@ public class LLAppExtreme extends LLAppPhone {
@Override @Override
public void onCreate() { public void onCreate() {
// obfuscation // obfuscation
String three = String.valueOf((new Date().getYear()+2901)/1000); String three = String.valueOf((new Date().getYear() + 2901) / 1000);
mIabKey = key1 + three + key2; mIabKey = key1 + three + key2;
mLicenseCheckerCallback = new MyLicenseCheckerCallback(); mLicenseCheckerCallback = new MyLicenseCheckerCallback();
mIabKey += three + key3 + three + key4 + getString(R.string.internal_version); mIabKey += three + key3 + three + key4 + getString(R.string.internal_version);
// obfuscation // obfuscation
mIabKey += key5 + three + key6; 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 intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Version.APP_STORE_INSTALL_PREFIX + context.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); context.startActivity(intent);
} catch(ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
// pass // pass
} }
Toast.makeText(context, "Couldn't validate the Play Store license. Please check your internet connectivity.", Toast.LENGTH_LONG).show(); 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); 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() { public String getIabKey() {
return mIabKey; 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() { public void checkLwpKey() {
// first step : the permission is granted meaning the package is installed // first step : the permission is granted meaning the package is installed
mHasLWPKey = checkPermission(LWP_PKG, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED; mHasLWPKey = checkPermission(LWP_PKG, Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED;
// second step, ask the key to check its license // second step, ask the key to check its license
new AsyncTask<Void,Void,Boolean>() { new AsyncTask<Void, Void, Boolean>() {
@Override @Override
protected Boolean doInBackground(Void... voids) { protected Boolean doInBackground(Void... voids) {
boolean hasLicensedKey = false; boolean hasLicensedKey = false;
try { 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) { if (c != null) {
c.moveToNext(); c.moveToNext();
hasLicensedKey = c.getInt(0) == 1; hasLicensedKey = c.getInt(0) == 1;
c.close(); c.close();
} }
} catch(Exception e) { } catch (Exception e) {
// pass // pass
} }
return hasLicensedKey; return hasLicensedKey;
@ -251,14 +220,14 @@ public class LLAppExtreme extends LLAppPhone {
@Override @Override
protected void onPostExecute(Boolean hasLicensedKey) { protected void onPostExecute(Boolean hasLicensedKey) {
// key is installed, but no license // key is installed, but no license
if(mHasLWPKey && !hasLicensedKey) { if (mHasLWPKey && !hasLicensedKey) {
LightningEngine engine = getAppEngine(); LightningEngine engine = getAppEngine();
engine.getGlobalConfig().lwpScreen = Page.NONE; engine.getGlobalConfig().lwpScreen = Page.NONE;
engine.notifyGlobalConfigChanged(); engine.notifyGlobalConfigChanged();
} }
mHasLWPKey = hasLicensedKey; mHasLWPKey = hasLicensedKey;
} }
}.execute((Void)null); }.execute((Void) null);
} }
@ -271,12 +240,12 @@ public class LLAppExtreme extends LLAppPhone {
mHasLWPIab = false; mHasLWPIab = false;
if(data.exists()) { if (data.exists()) {
JSONObject o = FileUtils.readJSONObjectFromFile(data); JSONObject o = FileUtils.readJSONObjectFromFile(data);
if(o != null) { if (o != null) {
try { try {
mHasLWPIab = o.getBoolean(getString(R.string.iab_lwp)); mHasLWPIab = o.getBoolean(getString(R.string.iab_lwp));
} catch(JSONException e) { } catch (JSONException e) {
// pass // pass
} }
} }
@ -284,7 +253,7 @@ public class LLAppExtreme extends LLAppPhone {
} }
public void setProductStatus(String sku, boolean purchased) { 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; mHasLWPIab = purchased;
} }
File data = getUnlockInfoDataFile(); 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) { public void checkProducts(final UnlockResultReceiver receiver) {
// Have we been disposed of in the meantime? If so, quit. // Have we been disposed of in the meantime? If so, quit.
if (mIABHelper == null || !mIABHelper.isSetupDone()) return; if (mIABHelper == null || !mIABHelper.isSetupDone()) return;
@ -318,12 +283,12 @@ public class LLAppExtreme extends LLAppPhone {
Purchase lwp = inventory.getPurchase(iab_lwp); Purchase lwp = inventory.getPurchase(iab_lwp);
boolean has_lwp = lwp != null /*&& verifyDeveloperPayload(unlock_pro)*/; boolean has_lwp = lwp != null /*&& verifyDeveloperPayload(unlock_pro)*/;
if(has_lwp) { if (has_lwp) {
setProductStatus(iab_lwp, true); setProductStatus(iab_lwp, true);
if(receiver != null) receiver.setUnlocked(iab_lwp, true); if (receiver != null) receiver.setUnlocked(iab_lwp, true);
} else { } else {
setProductStatus(iab_lwp, false); 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() { builder.setPositiveButton(context.getString(R.string.iab_y_key), new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { 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() { 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) { private void startPurchaseProcess(Context context, String sku) {
PurchaseProcess.startActivity(context, 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. * class.
*/ */
public class Base64 { public class Base64 {
/** Specify encoding (value is {@code true}). */ /**
* Specify encoding (value is {@code true}).
*/
public final static boolean ENCODE = 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; 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) '='; 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'; private final static byte NEW_LINE = (byte) '\n';
/** /**
* The 64 valid Base64 values. * The 64 valid Base64 values.
*/ */
private final static byte[] ALPHABET = private final static byte[] ALPHABET =
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
(byte) '9', (byte) '+', (byte) '/'}; (byte) '9', (byte) '+', (byte) '/'};
/** /**
* The 64 valid web safe Base64 values. * The 64 valid web safe Base64 values.
*/ */
private final static byte[] WEBSAFE_ALPHABET = private final static byte[] WEBSAFE_ALPHABET =
{(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
(byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
(byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
(byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
(byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
(byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
(byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
(byte) '9', (byte) '-', (byte) '_'}; (byte) '9', (byte) '-', (byte) '_'};
/** /**
* Translates a Base64 value to either its 6-bit reconstruction value * Translates a Base64 value to either its 6-bit reconstruction value
* or a negative number indicating some other meaning. * 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 private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed -5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12 -9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return -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, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31 -9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space -5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
62, // Plus sign at decimal 43 62, // Plus sign at decimal 43
-9, -9, -9, // Decimal 44 - 46 -9, -9, -9, // Decimal 44 - 46
63, // Slash at decimal 47 63, // Slash at decimal 47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60 -9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61 -1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64 -9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' 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' 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 -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' 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' 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 // 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, // 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 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 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 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 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 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 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 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,-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,-9,-9,-9 // Decimal 244 - 255 */
}; };
/** The web safe decodabet */ /**
* The web safe decodabet
*/
private final static byte[] WEBSAFE_DECODABET = private final static byte[] WEBSAFE_DECODABET =
{-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
-5, -5, // Whitespace: Tab and Linefeed -5, -5, // Whitespace: Tab and Linefeed
-9, -9, // Decimal 11 - 12 -9, -9, // Decimal 11 - 12
-5, // Whitespace: Carriage Return -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, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-9, -9, -9, -9, -9, // Decimal 27 - 31 -9, -9, -9, -9, -9, // Decimal 27 - 31
-5, // Whitespace: Space -5, // Whitespace: Space
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44 -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44
62, // Dash '-' sign at decimal 45 62, // Dash '-' sign at decimal 45
-9, -9, // Decimal 46-47 -9, -9, // Decimal 46-47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-9, -9, -9, // Decimal 58 - 60 -9, -9, -9, // Decimal 58 - 60
-1, // Equals sign at decimal 61 -1, // Equals sign at decimal 61
-9, -9, -9, // Decimal 62 - 64 -9, -9, -9, // Decimal 62 - 64
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' 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' 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-9, -9, -9, -9, // Decimal 91-94 -9, -9, -9, -9, // Decimal 91-94
63, // Underscore '_' at decimal 95 63, // Underscore '_' at decimal 95
-9, // Decimal 96 -9, // Decimal 96
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' 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' 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 // 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, // 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 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 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 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 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 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 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 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,-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,-9,-9,-9 // Decimal 244 - 255 */
}; };
// Indicates white space in encoding // Indicates white space in encoding
private final static byte WHITE_SPACE_ENC = -5; private final static byte WHITE_SPACE_ENC = -5;
// Indicates equals sign in encoding // Indicates equals sign in encoding
private final static byte EQUALS_SIGN_ENC = -1; private final static byte EQUALS_SIGN_ENC = -1;
/** Defeats instantiation. */ /**
* Defeats instantiation.
*/
private Base64() { private Base64() {
} }
@ -184,17 +196,17 @@ public class Base64 {
* The actual number of significant bytes in your array is * The actual number of significant bytes in your array is
* given by <var>numSigBytes</var>. * given by <var>numSigBytes</var>.
* *
* @param source the array to convert * @param source the array to convert
* @param srcOffset the index where conversion begins * @param srcOffset the index where conversion begins
* @param numSigBytes the number of significant bytes in your array * @param numSigBytes the number of significant bytes in your array
* @param destination the array to hold the conversion * @param destination the array to hold the conversion
* @param destOffset the index where output will be put * @param destOffset the index where output will be put
* @param alphabet is the encoding alphabet * @param alphabet is the encoding alphabet
* @return the <var>destination</var> array * @return the <var>destination</var> array
* @since 1.3 * @since 1.3
*/ */
private static byte[] encode3to4(byte[] source, int srcOffset, 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 // 1 2 3
// 01234567890123456789012345678901 Bit position // 01234567890123456789012345678901 Bit position
// --------000000001111111122222222 Array position from threeBytes // --------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. // when Java treats a value as negative that is cast from a byte to an int.
int inBuff = int inBuff =
(numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
switch (numSigBytes) { switch (numSigBytes) {
case 3: case 3:
@ -250,9 +262,9 @@ public class Base64 {
/** /**
* Encodes a byte array into web safe Base64 notation. * 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 * @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) { public static String encodeWebSafe(byte[] source, boolean doPadding) {
return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding); return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);
@ -261,22 +273,22 @@ public class Base64 {
/** /**
* Encodes a byte array into Base64 notation. * Encodes a byte array into Base64 notation.
* *
* @param source the data to convert * @param source the data to convert
* @param off offset in array where conversion should begin * @param off offset in array where conversion should begin
* @param len length of data to convert * @param len length of data to convert
* @param alphabet the encoding alphabet * @param alphabet the encoding alphabet
* @param doPadding is {@code true} to pad result with '=' chars * @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 * @since 1.4
*/ */
public static String encode(byte[] source, int off, int len, byte[] alphabet, 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); byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);
int outLen = outBuff.length; int outLen = outBuff.length;
// If doPadding is false, set length to truncate '=' // If doPadding is false, set length to truncate '='
// padding characters // padding characters
while (doPadding == false && outLen > 0) { while (!doPadding && outLen > 0) {
if (outBuff[outLen - 1] != '=') { if (outBuff[outLen - 1] != '=') {
break; break;
} }
@ -289,19 +301,19 @@ public class Base64 {
/** /**
* Encodes a byte array into Base64 notation. * Encodes a byte array into Base64 notation.
* *
* @param source the data to convert * @param source the data to convert
* @param off offset in array where conversion should begin * @param off offset in array where conversion should begin
* @param len length of data to convert * @param len length of data to convert
* @param alphabet is the encoding alphabet * @param alphabet is the encoding alphabet
* @param maxLineLength maximum length of one line. * @param maxLineLength maximum length of one line.
* @return the BASE64-encoded byte array * @return the BASE64-encoded byte array
*/ */
public static byte[] encode(byte[] source, int off, int len, byte[] alphabet, 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 lenDiv3 = (len + 2) / 3; // ceil(len / 3)
int len43 = lenDiv3 * 4; int len43 = lenDiv3 * 4;
byte[] outBuff = new byte[len43 // Main 4:3 byte[] outBuff = new byte[len43 // Main 4:3
+ (len43 / maxLineLength)]; // New lines + (len43 / maxLineLength)]; // New lines
int d = 0; int d = 0;
int e = 0; int e = 0;
@ -314,8 +326,8 @@ public class Base64 {
// but inlined for faster encoding (~20% improvement) // but inlined for faster encoding (~20% improvement)
int inBuff = int inBuff =
((source[d + off] << 24) >>> 8) ((source[d + off] << 24) >>> 8)
| ((source[d + 1 + off] << 24) >>> 16) | ((source[d + 1 + off] << 24) >>> 16)
| ((source[d + 2 + off] << 24) >>> 24); | ((source[d + 2 + off] << 24) >>> 24);
outBuff[e] = alphabet[(inBuff >>> 18)]; outBuff[e] = alphabet[(inBuff >>> 18)];
outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f]; outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f];
outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f]; outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f];
@ -363,22 +375,21 @@ public class Base64 {
* This method returns the actual number of bytes that * This method returns the actual number of bytes that
* were converted from the Base64 encoding. * were converted from the Base64 encoding.
* *
* * @param source the array to convert
* @param source the array to convert * @param srcOffset the index where conversion begins
* @param srcOffset the index where conversion begins
* @param destination the array to hold the conversion * @param destination the array to hold the conversion
* @param destOffset the index where output will be put * @param destOffset the index where output will be put
* @param decodabet the decodabet for decoding Base64 content * @param decodabet the decodabet for decoding Base64 content
* @return the number of decoded bytes converted * @return the number of decoded bytes converted
* @since 1.3 * @since 1.3
*/ */
private static int decode4to3(byte[] source, int srcOffset, private static int decode4to3(byte[] source, int srcOffset,
byte[] destination, int destOffset, byte[] decodabet) { byte[] destination, int destOffset, byte[] decodabet) {
// Example: Dk== // Example: Dk==
if (source[srcOffset + 2] == EQUALS_SIGN) { if (source[srcOffset + 2] == EQUALS_SIGN) {
int outBuff = int outBuff =
((decodabet[source[srcOffset]] << 24) >>> 6) ((decodabet[source[srcOffset]] << 24) >>> 6)
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12); | ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
destination[destOffset] = (byte) (outBuff >>> 16); destination[destOffset] = (byte) (outBuff >>> 16);
return 1; return 1;
@ -386,8 +397,8 @@ public class Base64 {
// Example: DkL= // Example: DkL=
int outBuff = int outBuff =
((decodabet[source[srcOffset]] << 24) >>> 6) ((decodabet[source[srcOffset]] << 24) >>> 6)
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12) | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18); | ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
destination[destOffset] = (byte) (outBuff >>> 16); destination[destOffset] = (byte) (outBuff >>> 16);
destination[destOffset + 1] = (byte) (outBuff >>> 8); destination[destOffset + 1] = (byte) (outBuff >>> 8);
@ -396,9 +407,9 @@ public class Base64 {
// Example: DkLE // Example: DkLE
int outBuff = int outBuff =
((decodabet[source[srcOffset]] << 24) >>> 6) ((decodabet[source[srcOffset]] << 24) >>> 6)
| ((decodabet[source[srcOffset + 1]] << 24) >>> 12) | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
| ((decodabet[source[srcOffset + 2]] << 24) >>> 18) | ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
| ((decodabet[source[srcOffset + 3]] << 24) >>> 24); | ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
destination[destOffset] = (byte) (outBuff >> 16); destination[destOffset] = (byte) (outBuff >> 16);
destination[destOffset + 1] = (byte) (outBuff >> 8); destination[destOffset + 1] = (byte) (outBuff >> 8);
@ -438,8 +449,8 @@ public class Base64 {
* *
* @param source The Base64 encoded data * @param source The Base64 encoded data
* @return decoded data * @return decoded data
* @since 1.3
* @throws Base64DecoderException * @throws Base64DecoderException
* @since 1.3
*/ */
public static byte[] decode(byte[] source) throws Base64DecoderException { public static byte[] decode(byte[] source) throws Base64DecoderException {
return decode(source, 0, source.length); return decode(source, 0, source.length);
@ -466,8 +477,8 @@ public class Base64 {
* @param off the offset of where to begin decoding * @param off the offset of where to begin decoding
* @param len the length of characters to decode * @param len the length of characters to decode
* @return decoded data * @return decoded data
* @since 1.3
* @throws Base64DecoderException * @throws Base64DecoderException
* @since 1.3
*/ */
public static byte[] decode(byte[] source, int off, int len) public static byte[] decode(byte[] source, int off, int len)
throws Base64DecoderException { throws Base64DecoderException {
@ -493,9 +504,9 @@ public class Base64 {
* Decodes Base64 content using the supplied decodabet and returns * Decodes Base64 content using the supplied decodabet and returns
* the decoded byte array. * the decoded byte array.
* *
* @param source the Base64 encoded data * @param source the Base64 encoded data
* @param off the offset of where to begin decoding * @param off the offset of where to begin decoding
* @param len the length of characters to decode * @param len the length of characters to decode
* @param decodabet the decodabet for decoding Base64 content * @param decodabet the decodabet for decoding Base64 content
* @return decoded data * @return decoded data
*/ */

View file

@ -44,22 +44,22 @@ import java.util.List;
* It provides synchronous (blocking) and asynchronous (non-blocking) methods for * It provides synchronous (blocking) and asynchronous (non-blocking) methods for
* many common in-app billing operations, as well as automatic signature * many common in-app billing operations, as well as automatic signature
* verification. * verification.
* * <p>
* After instantiating, you must perform setup in order to start using the object. * 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; * 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) * that listener will be notified when setup is complete, after which (and not before)
* you may call other methods. * you may call other methods.
* * <p>
* After setup is complete, you will typically want to request an inventory of owned * After setup is complete, you will typically want to request an inventory of owned
* items and subscriptions. See {@link #queryInventory}, {@link #queryInventoryAsync} * items and subscriptions. See {@link #queryInventory}, {@link #queryInventoryAsync}
* and related methods. * and related methods.
* * <p>
* When you are done with this object, don't forget to call {@link #dispose} * 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 * 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 * service, which will leak unless you dispose of it correctly. If you created
* the object on an Activity's onCreate method, then the recommended * the object on an Activity's onCreate method, then the recommended
* place to dispose of it is the Activity's onDestroy method. * 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 * 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 * call the blocking versions of methods; when using from a UI thread, call
* only the asynchronous versions and handle the results via callbacks. * 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. * has not yet completed will result in an exception being thrown.
* *
* @author Bruno Oliveira (Google) * @author Bruno Oliveira (Google)
*
*/ */
public class IabHelper { 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 // Billing response codes
public static final int BILLING_RESPONSE_RESULT_OK = 0; public static final int BILLING_RESPONSE_RESULT_OK = 0;
public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1; 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_ERROR = 6;
public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7; public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8; public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
// IAB Helper error codes // IAB Helper error codes
public static final int IABHELPER_ERROR_BASE = -1000; public static final int IABHELPER_ERROR_BASE = -1000;
public static final int IABHELPER_REMOTE_EXCEPTION = -1001; 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_UNKNOWN_ERROR = -1008;
public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009; public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009;
public static final int IABHELPER_INVALID_CONSUMPTION = -1010; public static final int IABHELPER_INVALID_CONSUMPTION = -1010;
// Keys for the responses from InAppBillingService // Keys for the responses from InAppBillingService
public static final String RESPONSE_CODE = "RESPONSE_CODE"; public static final String RESPONSE_CODE = "RESPONSE_CODE";
public static final String RESPONSE_GET_SKU_DETAILS_LIST = "DETAILS_LIST"; 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_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST";
public static final String RESPONSE_INAPP_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST"; public static final String RESPONSE_INAPP_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST";
public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN"; public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN";
// Item types // Item types
public static final String ITEM_TYPE_INAPP = "inapp"; public static final String ITEM_TYPE_INAPP = "inapp";
public static final String ITEM_TYPE_SUBS = "subs"; public static final String ITEM_TYPE_SUBS = "subs";
// some fields on the getSkuDetails response bundle // 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_LIST = "ITEM_ID_LIST";
public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = "ITEM_TYPE_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 * 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 * 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. * 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. * @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 * 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 * public key in your application's page on Google Play Developer Console. Note that this
* is NOT your "developer public key". * is NOT your "developer public key".
*/ */
public IabHelper(Context ctx, String base64PublicKey) { public IabHelper(Context ctx, String base64PublicKey) {
mContext = ctx.getApplicationContext(); mContext = ctx.getApplicationContext();
@ -168,6 +155,39 @@ public class IabHelper {
logDebug("IAB helper created."); 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. * Enables or disable debug logging through LogCat.
*/ */
@ -182,19 +202,6 @@ public class IabHelper {
mDebugLog = enable; 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. * 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. * You will be notified through the listener when the setup process is complete.
@ -225,9 +232,10 @@ public class IabHelper {
try { try {
logDebug("Checking for in-app billing 3 support."); logDebug("Checking for in-app billing 3 support.");
if(mService == null) { if (mService == null) {
if (listener != null) listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE, if (listener != null)
"Error checking for billing v3 support, no service.")); 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. // if in-app purchases aren't supported, neither are subscriptions.
mSubscriptionsSupported = false; mSubscriptionsSupported = false;
@ -251,17 +259,15 @@ public class IabHelper {
if (response == BILLING_RESPONSE_RESULT_OK) { if (response == BILLING_RESPONSE_RESULT_OK) {
logDebug("Subscriptions AVAILABLE."); logDebug("Subscriptions AVAILABLE.");
mSubscriptionsSupported = true; mSubscriptionsSupported = true;
} } else {
else {
logDebug("Subscriptions NOT AVAILABLE. Response: " + response); logDebug("Subscriptions NOT AVAILABLE. Response: " + response);
} }
mSetupDone = true; mSetupDone = true;
} } catch (RemoteException e) {
catch (RemoteException e) {
if (listener != null) { if (listener != null) {
listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION,
"RemoteException while setting up in-app billing.")); "RemoteException while setting up in-app billing."));
} }
e.printStackTrace(); e.printStackTrace();
return; return;
@ -280,13 +286,12 @@ public class IabHelper {
// service available to handle that Intent // service available to handle that Intent
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
mServiceBound = true; mServiceBound = true;
} } else {
else {
// no service available to handle that Intent // no service available to handle that Intent
if (listener != null) { if (listener != null) {
listener.onIabSetupFinished( listener.onIabSetupFinished(
new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE, 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() { 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() { public boolean subscriptionsSupported() {
checkNotDisposed(); checkNotDisposed();
return mSubscriptionsSupported; 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) { public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
launchPurchaseFlow(act, sku, requestCode, listener, ""); launchPurchaseFlow(act, sku, requestCode, listener, "");
} }
public void launchPurchaseFlow(Activity act, String sku, int requestCode, 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); launchPurchaseFlow(act, sku, ITEM_TYPE_INAPP, requestCode, listener, extraData);
} }
public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode,
OnIabPurchaseFinishedListener listener) { OnIabPurchaseFinishedListener listener) {
launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, ""); launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, "");
} }
public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, 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); 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 * this object's {@link #handleActivityResult} method to continue the purchase flow. This method
* MUST be called from the UI thread of the Activity. * MUST be called from the UI thread of the Activity.
* *
* @param act The calling activity. * @param act The calling activity.
* @param sku The sku of the item to purchase. * @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 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 -- * @param requestCode A request code (to differentiate from other responses --
* as in {@link Activity#startActivityForResult}). * as in {@link Activity#startActivityForResult}).
* @param listener The listener to notify when the purchase process finishes * @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 * @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 * when the purchase completes. This extra data will be permanently bound to that purchase
* and will always be returned when the purchase is queried. * and will always be returned when the purchase is queried.
*/ */
public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode, public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode,
OnIabPurchaseFinishedListener listener, String extraData) { OnIabPurchaseFinishedListener listener, String extraData) {
checkNotDisposed(); checkNotDisposed();
checkSetupDone("launchPurchaseFlow"); checkSetupDone("launchPurchaseFlow");
flagStartAsync("launchPurchaseFlow"); flagStartAsync("launchPurchaseFlow");
@ -419,19 +406,17 @@ public class IabHelper {
mPurchaseListener = listener; mPurchaseListener = listener;
mPurchasingItemType = itemType; mPurchasingItemType = itemType;
act.startIntentSenderForResult(pendingIntent.getIntentSender(), act.startIntentSenderForResult(pendingIntent.getIntentSender(),
requestCode, new Intent(), requestCode, new Intent(),
Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0)); Integer.valueOf(0));
} } catch (SendIntentException e) {
catch (SendIntentException e) {
logError("SendIntentException while launching purchase flow for sku " + sku); logError("SendIntentException while launching purchase flow for sku " + sku);
e.printStackTrace(); e.printStackTrace();
flagEndAsync(); flagEndAsync();
result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent."); result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent.");
if (listener != null) listener.onIabPurchaseFinished(result, null); if (listener != null) listener.onIabPurchaseFinished(result, null);
} } catch (RemoteException e) {
catch (RemoteException e) {
logError("RemoteException while launching purchase flow for sku " + sku); logError("RemoteException while launching purchase flow for sku " + sku);
e.printStackTrace(); e.printStackTrace();
flagEndAsync(); flagEndAsync();
@ -448,11 +433,11 @@ public class IabHelper {
* MUST be called from the UI thread of the Activity. * MUST be called from the UI thread of the Activity.
* *
* @param requestCode The requestCode as you received it. * @param requestCode The requestCode as you received it.
* @param resultCode The resultCode as you received it. * @param resultCode The resultCode as you received it.
* @param data The data (Intent) 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; * @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 * false if the result was not related to a purchase, in which case you should
* handle it normally. * handle it normally.
*/ */
public boolean handleActivityResult(int requestCode, int resultCode, Intent data) { public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result; IabResult result;
@ -486,7 +471,8 @@ public class IabHelper {
logError("BUG: either purchaseData or dataSignature is null."); logError("BUG: either purchaseData or dataSignature is null.");
logDebug("Extras: " + data.getExtras().toString()); logDebug("Extras: " + data.getExtras().toString());
result = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature"); 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; return true;
} }
@ -499,38 +485,36 @@ public class IabHelper {
if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) { if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) {
logError("Purchase signature verification FAILED for sku " + sku); logError("Purchase signature verification FAILED for sku " + sku);
result = new IabResult(IABHELPER_VERIFICATION_FAILED, "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; return true;
} }
logDebug("Purchase signature successfully verified."); logDebug("Purchase signature successfully verified.");
} } catch (JSONException e) {
catch (JSONException e) {
logError("Failed to parse purchase data."); logError("Failed to parse purchase data.");
e.printStackTrace(); e.printStackTrace();
result = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data."); 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; return true;
} }
if (mPurchaseListener != null) { if (mPurchaseListener != null) {
mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Success"), purchase); 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. // 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)); logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode));
if (mPurchaseListener != null) { if (mPurchaseListener != null) {
result = new IabResult(responseCode, "Problem purchashing item."); result = new IabResult(responseCode, "Problem purchashing item.");
mPurchaseListener.onIabPurchaseFinished(result, null); mPurchaseListener.onIabPurchaseFinished(result, null);
} }
} } else if (resultCode == Activity.RESULT_CANCELED) {
else if (resultCode == Activity.RESULT_CANCELED) {
logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode)); logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled."); result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
} } else {
else { logError("Purchase failed. Result code: " + resultCode
logError("Purchase failed. Result code: " + Integer.toString(resultCode)
+ ". Response: " + getResponseDesc(responseCode)); + ". Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response."); result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null); 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}. * 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 * @param querySkuDetails if true, SKU details (price, description, etc) will be queried as well
* as purchase information. * as purchase information.
* @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership. * @param moreItemSkus additional PRODUCT skus to query information on, regardless of ownership.
* Ignored if null or if querySkuDetails is false. * Ignored if null or if querySkuDetails is false.
* @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership. * @param moreSubsSkus additional SUBSCRIPTIONS skus to query information on, regardless of ownership.
* Ignored if null or if querySkuDetails is false. * Ignored if null or if querySkuDetails is false.
* @throws IabException if a problem occurs while refreshing the inventory. * @throws IabException if a problem occurs while refreshing the inventory.
*/ */
public Inventory queryInventory(boolean querySkuDetails, List<String> moreItemSkus, public Inventory queryInventory(boolean querySkuDetails, List<String> moreItemSkus,
List<String> moreSubsSkus) throws IabException { List<String> moreSubsSkus) throws IabException {
checkNotDisposed(); checkNotDisposed();
checkSetupDone("queryInventory"); checkSetupDone("queryInventory");
try { try {
@ -589,29 +573,13 @@ public class IabHelper {
} }
return inv; return inv;
} } catch (RemoteException e) {
catch (RemoteException e) {
throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while refreshing inventory.", 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); 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 * Asynchronous wrapper for inventory query. This will perform an inventory
* query as described in {@link #queryInventory}, but will do so asynchronously * query as described in {@link #queryInventory}, but will do so asynchronously
@ -619,12 +587,12 @@ public class IabHelper {
* call from a UI thread. * call from a UI thread.
* *
* @param querySkuDetails as in {@link #queryInventory} * @param querySkuDetails as in {@link #queryInventory}
* @param moreSkus as in {@link #queryInventory} * @param moreSkus as in {@link #queryInventory}
* @param listener The listener to notify when the refresh operation completes. * @param listener The listener to notify when the refresh operation completes.
*/ */
public void queryInventoryAsync(final boolean querySkuDetails, public void queryInventoryAsync(final boolean querySkuDetails,
final List<String> moreSkus, final List<String> moreSkus,
final QueryInventoryFinishedListener listener) { final QueryInventoryFinishedListener listener) {
final Handler handler = new Handler(); final Handler handler = new Handler();
checkNotDisposed(); checkNotDisposed();
checkSetupDone("queryInventory"); checkSetupDone("queryInventory");
@ -639,8 +607,7 @@ public class IabHelper {
Inventory inv = null; Inventory inv = null;
try { try {
inv = queryInventory(querySkuDetails, moreSkus); inv = queryInventory(querySkuDetails, moreSkus);
} } catch (IabException ex) {
catch (IabException ex) {
result = ex.getResult(); result = ex.getResult();
} }
@ -667,7 +634,6 @@ public class IabHelper {
queryInventoryAsync(querySkuDetails, null, listener); queryInventoryAsync(querySkuDetails, null, listener);
} }
/** /**
* Consumes a given in-app product. Consuming can only be done on an item * 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. * 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 token = itemInfo.getToken();
String sku = itemInfo.getSku(); String sku = itemInfo.getSku();
if (token == null || token.equals("")) { if (token == null || token.equals("")) {
logError("Can't consume "+ sku + ". No token."); logError("Can't consume " + sku + ". No token.");
throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: " throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: "
+ sku + " " + itemInfo); + sku + " " + itemInfo);
} }
logDebug("Consuming sku: " + sku + ", token: " + token); logDebug("Consuming sku: " + sku + ", token: " + token);
int response = mService.consumePurchase(3, mContext.getPackageName(), token); int response = mService.consumePurchase(3, mContext.getPackageName(), token);
if (response == BILLING_RESPONSE_RESULT_OK) { 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 { } catch (RemoteException e) {
logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response));
throw new IabException(response, "Error consuming sku " + sku);
}
}
catch (RemoteException e) {
throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while consuming. PurchaseInfo: " + itemInfo, 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 * Asynchronous wrapper to item consumption. Works like {@link #consume}, but
* performs the consumption in the background and notifies completion through * 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. * Same as {@link consumeAsync}, but for multiple items at once.
*
* @param purchases The list of PurchaseInfo objects representing the purchases to consume. * @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) { public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) {
checkNotDisposed(); checkNotDisposed();
@ -764,41 +702,6 @@ public class IabHelper {
consumeAsyncInternal(purchases, null, listener); 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. // Checks that setup was done; if not, throws an exception.
void checkSetupDone(String operation) { void checkSetupDone(String operation) {
if (!mSetupDone) { if (!mSetupDone) {
@ -813,9 +716,8 @@ public class IabHelper {
if (o == null) { if (o == null) {
logDebug("Bundle with null response code, assuming OK (known issue)"); logDebug("Bundle with null response code, assuming OK (known issue)");
return BILLING_RESPONSE_RESULT_OK; return BILLING_RESPONSE_RESULT_OK;
} } else if (o instanceof Integer) return ((Integer) o).intValue();
else if (o instanceof Integer) return ((Integer)o).intValue(); else if (o instanceof Long) return (int) ((Long) o).longValue();
else if (o instanceof Long) return (int)((Long)o).longValue();
else { else {
logError("Unexpected type for bundle response code."); logError("Unexpected type for bundle response code.");
logError(o.getClass().getName()); logError(o.getClass().getName());
@ -829,9 +731,8 @@ public class IabHelper {
if (o == null) { if (o == null) {
logError("Intent with no response code, assuming OK (known issue)"); logError("Intent with no response code, assuming OK (known issue)");
return BILLING_RESPONSE_RESULT_OK; return BILLING_RESPONSE_RESULT_OK;
} } else if (o instanceof Integer) return ((Integer) o).intValue();
else if (o instanceof Integer) return ((Integer)o).intValue(); else if (o instanceof Long) return (int) ((Long) o).longValue();
else if (o instanceof Long) return (int)((Long)o).longValue();
else { else {
logError("Unexpected type for intent response code."); logError("Unexpected type for intent response code.");
logError(o.getClass().getName()); logError(o.getClass().getName());
@ -853,7 +754,6 @@ public class IabHelper {
mAsyncInProgress = false; mAsyncInProgress = false;
} }
int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException { int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException {
// Query purchases // Query purchases
logDebug("Querying owned items, item type: " + itemType); logDebug("Querying owned items, item type: " + itemType);
@ -867,7 +767,7 @@ public class IabHelper {
itemType, continueToken); itemType, continueToken);
int response = getResponseCodeFromBundle(ownedItems); int response = getResponseCodeFromBundle(ownedItems);
logDebug("Owned items response: " + String.valueOf(response)); logDebug("Owned items response: " + response);
if (response != BILLING_RESPONSE_RESULT_OK) { if (response != BILLING_RESPONSE_RESULT_OK) {
logDebug("getPurchases() failed: " + getResponseDesc(response)); logDebug("getPurchases() failed: " + getResponseDesc(response));
return response; return response;
@ -880,11 +780,11 @@ public class IabHelper {
} }
ArrayList<String> ownedSkus = ownedItems.getStringArrayList( ArrayList<String> ownedSkus = ownedItems.getStringArrayList(
RESPONSE_INAPP_ITEM_LIST); RESPONSE_INAPP_ITEM_LIST);
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList( ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(
RESPONSE_INAPP_PURCHASE_DATA_LIST); RESPONSE_INAPP_PURCHASE_DATA_LIST);
ArrayList<String> signatureList = ownedItems.getStringArrayList( ArrayList<String> signatureList = ownedItems.getStringArrayList(
RESPONSE_INAPP_SIGNATURE_LIST); RESPONSE_INAPP_SIGNATURE_LIST);
for (int i = 0; i < purchaseDataList.size(); ++i) { for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i); String purchaseData = purchaseDataList.get(i);
@ -901,8 +801,7 @@ public class IabHelper {
// Record ownership and token // Record ownership and token
inv.addPurchase(purchase); inv.addPurchase(purchase);
} } else {
else {
logWarn("Purchase signature verification **FAILED**. Not adding item."); logWarn("Purchase signature verification **FAILED**. Not adding item.");
logDebug(" Purchase data: " + purchaseData); logDebug(" Purchase data: " + purchaseData);
logDebug(" Signature: " + signature); logDebug(" Signature: " + signature);
@ -918,7 +817,7 @@ public class IabHelper {
} }
int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus) int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus)
throws RemoteException, JSONException { throws RemoteException, JSONException {
logDebug("Querying SKU details."); logDebug("Querying SKU details.");
ArrayList<String> skuList = new ArrayList<String>(); ArrayList<String> skuList = new ArrayList<String>();
skuList.addAll(inv.getAllOwnedSkus(itemType)); skuList.addAll(inv.getAllOwnedSkus(itemType));
@ -945,8 +844,7 @@ public class IabHelper {
if (response != BILLING_RESPONSE_RESULT_OK) { if (response != BILLING_RESPONSE_RESULT_OK) {
logDebug("getSkuDetails() failed: " + getResponseDesc(response)); logDebug("getSkuDetails() failed: " + getResponseDesc(response));
return response; return response;
} } else {
else {
logError("getSkuDetails() returned a bundle with neither an error nor a detail list."); logError("getSkuDetails() returned a bundle with neither an error nor a detail list.");
return IABHELPER_BAD_RESPONSE; return IABHELPER_BAD_RESPONSE;
} }
@ -963,7 +861,6 @@ public class IabHelper {
return BILLING_RESPONSE_RESULT_OK; return BILLING_RESPONSE_RESULT_OK;
} }
void consumeAsyncInternal(final List<Purchase> purchases, void consumeAsyncInternal(final List<Purchase> purchases,
final OnConsumeFinishedListener singleListener, final OnConsumeFinishedListener singleListener,
final OnConsumeMultiFinishedListener multiListener) { final OnConsumeMultiFinishedListener multiListener) {
@ -976,8 +873,7 @@ public class IabHelper {
try { try {
consume(purchase); consume(purchase);
results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, "Successful consume of sku " + purchase.getSku())); results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, "Successful consume of sku " + purchase.getSku()));
} } catch (IabException ex) {
catch (IabException ex) {
results.add(ex.getResult()); results.add(ex.getResult());
} }
} }
@ -1012,4 +908,74 @@ public class IabHelper {
void logWarn(String msg) { void logWarn(String msg) {
Log.w(mDebugTag, "In-app billing warning: " + 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}. * An Inventory is returned by such methods as {@link IabHelper#queryInventory}.
*/ */
public class Inventory { public class Inventory {
Map<String,SkuDetails> mSkuMap = new HashMap<String,SkuDetails>(); Map<String, SkuDetails> mSkuMap = new HashMap<String, SkuDetails>();
Map<String,Purchase> mPurchaseMap = new HashMap<String,Purchase>(); 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) { public SkuDetails getSkuDetails(String sku) {
return mSkuMap.get(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) { public Purchase getPurchase(String sku) {
return mPurchaseMap.get(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) { public boolean hasPurchase(String sku) {
return mPurchaseMap.containsKey(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) { public boolean hasDetails(String sku) {
return mSkuMap.containsKey(sku); return mSkuMap.containsKey(sku);
} }
@ -59,15 +68,19 @@ public class Inventory {
* a new Inventory. * a new Inventory.
*/ */
public void erasePurchase(String sku) { 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() { List<String> getAllOwnedSkus() {
return new ArrayList<String>(mPurchaseMap.keySet()); 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> getAllOwnedSkus(String itemType) {
List<String> result = new ArrayList<String>(); List<String> result = new ArrayList<String>();
for (Purchase p : mPurchaseMap.values()) { for (Purchase p : mPurchaseMap.values()) {
@ -76,7 +89,9 @@ public class Inventory {
return result; return result;
} }
/** Returns a list of all purchases. */ /**
* Returns a list of all purchases.
*/
List<Purchase> getAllPurchases() { List<Purchase> getAllPurchases() {
return new ArrayList<Purchase>(mPurchaseMap.values()); return new ArrayList<Purchase>(mPurchaseMap.values());
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,33 +24,6 @@ SOFTWARE.
package net.pierrox.lightning_launcher.activities; 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.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -79,14 +52,41 @@ import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; 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 { 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_BACKUP_IN_PROGRESS = 1;
private static final int DIALOG_RESTORE_IN_PROGRESS=2; private static final int DIALOG_RESTORE_IN_PROGRESS = 2;
private static final int DIALOG_SELECT_ARCHIVE_NAME=3; private static final int DIALOG_SELECT_ARCHIVE_NAME = 3;
private static final int DIALOG_SELECT_BACKUP_ACTION=4; private static final int DIALOG_SELECT_BACKUP_ACTION = 4;
private static final int DIALOG_CONFIRM_RESTORE=5; private static final int DIALOG_CONFIRM_RESTORE = 5;
private static final int DIALOG_CONFIRM_DELETE=6; private static final int DIALOG_CONFIRM_DELETE = 6;
private static final int REQUEST_SELECT_PAGES_FOR_EXPORT = 1; 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_IMPORT = 2;
private static final int REQUEST_SELECT_FILE_TO_LOAD = 3; 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 boolean mSelectArchiveNameForBackup;
private String mArchiveName; private String mArchiveName;
private Uri mArchiveUri; private Uri mArchiveUri;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME); Utils.setTheme(this, Utils.APP_THEME);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.backup_restore); 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.setText(R.string.backup_t);
backup.setOnClickListener(this); backup.setOnClickListener(this);
Button import_ = (Button) findViewById(R.id.import_); Button import_ = findViewById(R.id.import_);
import_.setText(R.string.import_t); import_.setText(R.string.import_t);
import_.setOnClickListener(this); import_.setOnClickListener(this);
import_.setOnLongClickListener(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.setText(R.string.tmpl_e_t);
export.setOnClickListener(this); export.setOnClickListener(this);
export.setOnLongClickListener(this); export.setOnLongClickListener(this);
mListView = (ListView) findViewById(R.id.archives); mListView = findViewById(R.id.archives);
mListView.setOnItemClickListener(this); mListView.setOnItemClickListener(this);
mListView.setOnItemLongClickListener(this); mListView.setOnItemLongClickListener(this);
mEmptyView = (TextView) findViewById(R.id.empty); mEmptyView = findViewById(R.id.empty);
mEmptyView.setText(R.string.no_backup_archive); mEmptyView.setText(R.string.no_backup_archive);
loadArchivesList(); loadArchivesList();
if(LLApp.get().isTrialVersion()) { if (LLApp.get().isTrialVersion()) {
Toast.makeText(this, R.string.tr_fl_t, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.tr_fl_t, Toast.LENGTH_SHORT).show();
} else { } else {
checkPermissions( checkPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 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); REQUEST_PERMISSION_BASE);
} }
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(areAllPermissionsGranted(grantResults, R.string.pr_f1)) { if (areAllPermissionsGranted(grantResults, R.string.pr_f1)) {
loadArchivesList(); loadArchivesList();
} }
} }
@ -151,7 +151,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
super.onResume(); super.onResume();
Intent intent = getIntent(); Intent intent = getIntent();
if(Intent.ACTION_VIEW.equals(intent.getAction())) { if (Intent.ACTION_VIEW.equals(intent.getAction())) {
intent.setAction(Intent.ACTION_MAIN); intent.setAction(Intent.ACTION_MAIN);
loadArchive(intent.getData(), null); loadArchive(intent.getData(), null);
} }
@ -164,7 +164,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
return !file.isDirectory(); return !file.isDirectory();
} }
}); });
if(archives==null || archives.length==0) { if (archives == null || archives.length == 0) {
mEmptyView.setVisibility(View.VISIBLE); mEmptyView.setVisibility(View.VISIBLE);
mListView.setVisibility(View.GONE); mListView.setVisibility(View.GONE);
} else { } else {
@ -173,13 +173,13 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
public int compare(File file1, File file2) { public int compare(File file1, File file2) {
long a = file1.lastModified(); long a = file1.lastModified();
long b = file2.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; return 0;
} }
}); });
String[] archives_names = new String[archives.length]; 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(); archives_names[i] = archives[i].getName();
} }
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, archives_names); 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; break;
} }
} }
@Override @Override
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
switch(view.getId()) { switch (view.getId()) {
case R.id.export: case R.id.export:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.pierrox.net/cmsms/applications/lightning-launcher/templates.html"))); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.pierrox.net/cmsms/applications/lightning-launcher/templates.html")));
return true; return true;
@ -217,15 +217,15 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
selectFileToLoadOrImport(false); selectFileToLoadOrImport(false);
return true; return true;
} }
return false; return false;
} }
@Override @Override
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder; AlertDialog.Builder builder;
ProgressDialog progress; ProgressDialog progress;
switch(id) { switch (id) {
case DIALOG_BACKUP_IN_PROGRESS: case DIALOG_BACKUP_IN_PROGRESS:
progress = new ProgressDialog(this); progress = new ProgressDialog(this);
progress.setMessage(getString(R.string.backup_in_progress)); 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 = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_n); builder.setTitle(R.string.br_n);
final String archive_name; final String archive_name;
if(mArchiveName == null) { if (mArchiveName == null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm"); 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 { } else {
archive_name = mArchiveName; archive_name = mArchiveName;
} }
@ -259,18 +259,18 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
@Override @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
String name = edit_text.getText().toString().trim(); String name = edit_text.getText().toString().trim();
String archive_path= FileUtils.LL_EXT_DIR +"/"+name; String archive_path = FileUtils.LL_EXT_DIR + "/" + name;
File old_archive_file = mArchiveName==null ? null : new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName); File old_archive_file = mArchiveName == null ? null : new File(FileUtils.LL_EXT_DIR + "/" + mArchiveName);
if(old_archive_file!=null && old_archive_file.exists()) { if (old_archive_file != null && old_archive_file.exists()) {
old_archive_file.renameTo(new File(archive_path)); old_archive_file.renameTo(new File(archive_path));
loadArchivesList(); loadArchivesList();
} else { } else {
if(mSelectArchiveNameForBackup) { if (mSelectArchiveNameForBackup) {
new BackupTask().execute(archive_path); new BackupTask().execute(archive_path);
} else { } else {
mArchiveName = FileUtils.LL_EXT_DIR +"/"+name; mArchiveName = FileUtils.LL_EXT_DIR + "/" + name;
selectDesktopsToExport(); selectDesktopsToExport();
} }
} }
} }
}); });
@ -278,14 +278,14 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
return builder.create(); return builder.create();
case DIALOG_CONFIRM_RESTORE: case DIALOG_CONFIRM_RESTORE:
if(mArchiveName != null || mArchiveUri != null) { if (mArchiveName != null || mArchiveUri != null) {
builder = new AlertDialog.Builder(this); builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_rc); 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() { builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
if(mArchiveName == null) { if (mArchiveName == null) {
new RestoreTask(mArchiveUri).execute(); new RestoreTask(mArchiveUri).execute();
} else { } else {
String path; String path;
@ -304,14 +304,14 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
break; break;
case DIALOG_CONFIRM_DELETE: case DIALOG_CONFIRM_DELETE:
if(mArchiveName != null) { if (mArchiveName != null) {
builder = new AlertDialog.Builder(this); builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_dc); builder.setTitle(R.string.br_dc);
builder.setMessage(mArchiveName); builder.setMessage(mArchiveName);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName).delete(); new File(FileUtils.LL_EXT_DIR + "/" + mArchiveName).delete();
loadArchivesList(); loadArchivesList();
} }
}); });
@ -321,37 +321,43 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
break; break;
case DIALOG_SELECT_BACKUP_ACTION: case DIALOG_SELECT_BACKUP_ACTION:
if(mArchiveName != null) { if (mArchiveName != null) {
builder = new AlertDialog.Builder(this); builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_a); 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 @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
switch(i) { switch (i) {
case 0: case 0:
new BackupTask().execute(FileUtils.LL_EXT_DIR +"/"+mArchiveName); new BackupTask().execute(FileUtils.LL_EXT_DIR + "/" + mArchiveName);
break; break;
case 1: case 1:
mArchiveName = FileUtils.LL_EXT_DIR +"/"+mArchiveName; mArchiveName = FileUtils.LL_EXT_DIR + "/" + mArchiveName;
selectDesktopsToExport(); selectDesktopsToExport();
break; break;
case 2: 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); showDialog(DIALOG_SELECT_ARCHIVE_NAME);
break; break;
case 3: case 3:
Intent shareIntent = new Intent(); Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND); 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.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("application/zip"); shareIntent.setType("application/zip");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.br_s))); startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.br_s)));
break; break;
case 4: case 4:
try { removeDialog(DIALOG_CONFIRM_DELETE); } catch(Exception e) {} try {
removeDialog(DIALOG_CONFIRM_DELETE);
} catch (Exception e) {
}
showDialog(DIALOG_CONFIRM_DELETE); showDialog(DIALOG_CONFIRM_DELETE);
break; break;
} }
@ -372,7 +378,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
} }
private void loadArchive(Uri archiveUri, String archiveName) { private void loadArchive(Uri archiveUri, String archiveName) {
if(LLApp.get().isTrialVersion()) { if (LLApp.get().isTrialVersion()) {
LLApp.get().showFeatureLockedDialog(this); LLApp.get().showFeatureLockedDialog(this);
} else { } else {
mArchiveUri = archiveUri; mArchiveUri = archiveUri;
@ -391,57 +397,60 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
showDialog(DIALOG_SELECT_BACKUP_ACTION); showDialog(DIALOG_SELECT_BACKUP_ACTION);
return true; return true;
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUEST_SELECT_PAGES_FOR_EXPORT) { if (requestCode == REQUEST_SELECT_PAGES_FOR_EXPORT) {
if(resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
int[] selected_pages = data.getIntArrayExtra(API.SCREEN_PICKER_INTENT_EXTRA_SELECTED_SCREENS); int[] selected_pages = data.getIntArrayExtra(API.SCREEN_PICKER_INTENT_EXTRA_SELECTED_SCREENS);
ArrayList<Integer> all_pages = new ArrayList<Integer>(); ArrayList<Integer> all_pages = new ArrayList<Integer>();
for(int p : selected_pages) { for (int p : selected_pages) {
all_pages.add(Integer.valueOf(p)); all_pages.add(Integer.valueOf(p));
addSubPages(all_pages, p); addSubPages(all_pages, p);
} }
all_pages.add(Integer.valueOf(Page.APP_DRAWER_PAGE)); all_pages.add(Integer.valueOf(Page.APP_DRAWER_PAGE));
all_pages.add(Integer.valueOf(Page.USER_MENU_PAGE)); all_pages.add(Integer.valueOf(Page.USER_MENU_PAGE));
doExportTemplate(mArchiveName, all_pages); doExportTemplate(mArchiveName, all_pages);
} }
} else if(requestCode == REQUEST_SELECT_FILE_TO_IMPORT){ } else if (requestCode == REQUEST_SELECT_FILE_TO_IMPORT) {
if(resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
importFile(data.getData()); importFile(data.getData());
} }
} else if(requestCode == REQUEST_SELECT_FILE_TO_LOAD){ } else if (requestCode == REQUEST_SELECT_FILE_TO_LOAD) {
if(resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
loadArchive(data.getData(), null); loadArchive(data.getData(), null);
} }
} else { } else {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
} }
} }
private void addSubPages(ArrayList<Integer> all_pages, int p) { private void addSubPages(ArrayList<Integer> all_pages, int p) {
Page page = LLApp.get().getAppEngine().getOrLoadPage(p); Page page = LLApp.get().getAppEngine().getOrLoadPage(p);
for(Item i : page.items) { for (Item i : page.items) {
if(i instanceof Folder) { if (i instanceof Folder) {
int folder_page_id = ((Folder)i).getFolderPageId(); int folder_page_id = ((Folder) i).getFolderPageId();
all_pages.add(Integer.valueOf(folder_page_id)); all_pages.add(Integer.valueOf(folder_page_id));
addSubPages(all_pages, folder_page_id); addSubPages(all_pages, folder_page_id);
} }
} }
} }
private void exportArchive(boolean for_backup) { private void exportArchive(boolean for_backup) {
mSelectArchiveNameForBackup = for_backup; mSelectArchiveNameForBackup = for_backup;
mArchiveName = null; mArchiveName = null;
try { removeDialog(DIALOG_SELECT_ARCHIVE_NAME); } catch(Exception e) {} try {
removeDialog(DIALOG_SELECT_ARCHIVE_NAME);
} catch (Exception e) {
}
showDialog(DIALOG_SELECT_ARCHIVE_NAME); showDialog(DIALOG_SELECT_ARCHIVE_NAME);
} }
private void selectDesktopsToExport() { private void selectDesktopsToExport() {
Intent intent = new Intent(this, ScreenManager.class); 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_SELECTED_SCREENS, LLApp.get().getAppEngine().getGlobalConfig().screensOrder);
intent.putExtra(API.SCREEN_PICKER_INTENT_EXTRA_TITLE, getString(R.string.tmpl_s_p)); intent.putExtra(API.SCREEN_PICKER_INTENT_EXTRA_TITLE, getString(R.string.tmpl_s_p));
startActivityForResult(intent, REQUEST_SELECT_PAGES_FOR_EXPORT); startActivityForResult(intent, REQUEST_SELECT_PAGES_FOR_EXPORT);
@ -465,27 +474,27 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
@Override @Override
protected Boolean doInBackground(Void... voids) { protected Boolean doInBackground(Void... voids) {
BackupRestoreTool.BackupConfig backup_config=new BackupRestoreTool.BackupConfig(); BackupRestoreTool.BackupConfig backup_config = new BackupRestoreTool.BackupConfig();
backup_config.context=BackupRestore.this; backup_config.context = BackupRestore.this;
PackageManager pm=getPackageManager(); PackageManager pm = getPackageManager();
try { try {
PackageInfo pi=pm.getPackageInfo(BackupRestore.this.getPackageName(), 0); PackageInfo pi = pm.getPackageInfo(BackupRestore.this.getPackageName(), 0);
final String data_dir=pi.applicationInfo.dataDir+"/files"; final String data_dir = pi.applicationInfo.dataDir + "/files";
backup_config.pathFrom=data_dir; backup_config.pathFrom = data_dir;
} catch(PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
// pass // pass
} }
backup_config.pathTo=backup_path; backup_config.pathTo = backup_path;
backup_config.includeWidgetsData=true; backup_config.includeWidgetsData = true;
backup_config.includeWallpaper=true; backup_config.includeWallpaper = true;
backup_config.includeFonts=true; backup_config.includeFonts = true;
backup_config.forTemplate =true; backup_config.forTemplate = true;
backup_config.statusBarHeight = sb_height; backup_config.statusBarHeight = sb_height;
backup_config.pagesToInclude = included_pages; backup_config.pagesToInclude = included_pages;
return BackupRestoreTool.backup(backup_config)==null; return BackupRestoreTool.backup(backup_config) == null;
} }
@Override @Override
@ -496,140 +505,10 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
} }
}.execute((Void) null); }.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. * 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. * @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) { private void selectFileToLoadOrImport(boolean only_load) {
@ -666,20 +545,26 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
FileUtils.copyStream(is, os); FileUtils.copyStream(is, os);
return outFile; return outFile;
} catch (IOException e) { } catch (IOException e) {
if(outFile != null) { if (outFile != null) {
outFile.delete(); outFile.delete();
} }
return null; return null;
} finally { } finally {
try { if(is != null) is.close(); } catch(IOException e) {} try {
try { if(os != null) os.close(); } catch(IOException e) {} if (is != null) is.close();
} catch (IOException e) {
}
try {
if (os != null) os.close();
} catch (IOException e) {
}
} }
} }
@Override @Override
protected void onPostExecute(File outFile) { protected void onPostExecute(File outFile) {
mDialog.dismiss(); mDialog.dismiss();
if(outFile != null) { if (outFile != null) {
loadArchivesList(); loadArchivesList();
loadArchive(null, outFile.getName()); loadArchive(null, outFile.getName());
} else { } else {
@ -706,4 +591,139 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
} }
return name; 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 boolean mEventActionForPickNew;
private LightningEngine mAppEngine; 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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR); 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); mType = intent.getIntExtra(INTENT_EXTRA_TYPE, Action.FLAG_TYPE_DESKTOP);
String s; String s;
if(savedInstanceState != null) { if (savedInstanceState != null) {
s = savedInstanceState.getString(INTENT_EXTRA_EVENT_ACTION_LIST); s = savedInstanceState.getString(INTENT_EXTRA_EVENT_ACTION_LIST);
String p = savedInstanceState.getString(SIS_EVENT_ACTION_PICK); String p = savedInstanceState.getString(SIS_EVENT_ACTION_PICK);
mEventActionForPickNew = savedInstanceState.getBoolean(SIS_EVENT_ACTION_PICK_NEW); mEventActionForPickNew = savedInstanceState.getBoolean(SIS_EVENT_ACTION_PICK_NEW);
if(p != null) { if (p != null) {
mEventActionForPick = new EventAction(); mEventActionForPick = new EventAction();
try { try {
JsonLoader.loadFieldsFromJSONObject(mEventActionForPick, new JSONObject(p), null); JsonLoader.loadFieldsFromJSONObject(mEventActionForPick, new JSONObject(p), null);
@ -161,13 +190,13 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
Window window = getWindow(); Window window = getWindow();
window.setBackgroundDrawable(decorView.getBackground()); window.setBackgroundDrawable(decorView.getBackground());
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT); window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
View dialogContent = ((ViewGroup)decorView.findViewById(android.R.id.content)).getChildAt(0); View dialogContent = ((ViewGroup) decorView.findViewById(android.R.id.content)).getChildAt(0);
((ViewGroup)dialogContent.getParent()).removeView(dialogContent); ((ViewGroup) dialogContent.getParent()).removeView(dialogContent);
dialog.dismiss(); dialog.dismiss();
setContentView(dialogContent); 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); mAdapter = new EventActionAdapter(this, mEventActions);
list.setAdapter(mAdapter); list.setAdapter(mAdapter);
list.setOnItemClickListener(this); list.setOnItemClickListener(this);
@ -196,7 +225,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
} }
}); });
if(mEventActions.size() == 0) { if (mEventActions.size() == 0) {
addAction(); addAction();
} }
} }
@ -212,41 +241,12 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
outState.putString(INTENT_EXTRA_EVENT_ACTION_LIST, serializeEventAction()); 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.putString(SIS_EVENT_ACTION_PICK, JsonLoader.toJSONObject(mEventActionForPick, null).toString());
outState.putBoolean(SIS_EVENT_ACTION_PICK_NEW, mEventActionForPickNew); 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 @Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
editAction(mAdapter.getItem(i), false); editAction(mAdapter.getItem(i), false);
@ -254,14 +254,14 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
private void deserializeEventActionList(String s) { private void deserializeEventActionList(String s) {
mEventActions = new ArrayList<>(); mEventActions = new ArrayList<>();
if(s != null) { if (s != null) {
try { try {
JSONObject json = new JSONObject(s); JSONObject json = new JSONObject(s);
EventAction ea = new EventAction(); EventAction ea = new EventAction();
JsonLoader.loadFieldsFromJSONObject(ea, json, null); JsonLoader.loadFieldsFromJSONObject(ea, json, null);
while(ea != null) { while (ea != null) {
if(ea.action != GlobalConfig.UNSET) { if (ea.action != GlobalConfig.UNSET) {
mEventActions.add(ea); mEventActions.add(ea);
} }
EventAction ea_tmp = ea.next; EventAction ea_tmp = ea.next;
@ -278,8 +278,8 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
EventAction current = null; EventAction current = null;
EventAction first = null; EventAction first = null;
for (EventAction ea : mEventActions) { for (EventAction ea : mEventActions) {
if(ea.action == GlobalConfig.UNSET) continue; if (ea.action == GlobalConfig.UNSET) continue;
if(current == null) { if (current == null) {
current = ea; current = ea;
first = ea; first = ea;
} else { } else {
@ -288,7 +288,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
} }
} }
if(first == null) { if (first == null) {
first = new EventAction(GlobalConfig.UNSET, null); first = new EventAction(GlobalConfig.UNSET, null);
} }
JSONObject out = JsonLoader.toJSONObject(first, null); JSONObject out = JsonLoader.toJSONObject(first, null);
@ -304,7 +304,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
private void saveAndFinish() { private void saveAndFinish() {
String serializedEventAction = serializeEventAction(); String serializedEventAction = serializeEventAction();
Intent intent; Intent intent;
if(mForShortcut) { if (mForShortcut) {
Intent i = new Intent(this, Dashboard.class); Intent i = new Intent(this, Dashboard.class);
i.putExtra(LightningIntent.INTENT_EXTRA_EVENT_ACTION, serializedEventAction); i.putExtra(LightningIntent.INTENT_EXTRA_EVENT_ACTION, serializedEventAction);
String name = mActions.getActionName(mEventActions.size() == 0 ? GlobalConfig.UNSET : mEventActions.get(0).action); 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); Intent i = new Intent(Intent.ACTION_PICK_ACTIVITY);
i.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT)); i.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT));
i.putExtra(Intent.EXTRA_TITLE, getString(R.string.tools_pick_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) { } else if (new_action == GlobalConfig.RUN_SCRIPT) {
ScriptPickerDialog dialog = new ScriptPickerDialog(this, mAppEngine, ea.data, Script.TARGET_NONE, new ScriptPickerDialog.OnScriptPickerEvent() { ScriptPickerDialog dialog = new ScriptPickerDialog(this, mAppEngine, ea.data, Script.TARGET_NONE, new ScriptPickerDialog.OnScriptPickerEvent() {
@Override @Override
@ -363,7 +366,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
@Override @Override
public void onScriptPickerCanceled() { public void onScriptPickerCanceled() {
if(mEventActionForPickNew) { if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick); mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
} }
@ -380,7 +383,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
@Override @Override
public void onNoFolderSelected() { public void onNoFolderSelected() {
if(mEventActionForPickNew) { if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick); mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
} }
@ -401,7 +404,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
@Override @Override
public void onSetVariableCancel() { public void onSetVariableCancel() {
if(mEventActionForPickNew) { if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick); mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
} }
@ -416,7 +419,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
startActivityForResult(data, REQUEST_PICK_SHORTCUT2); startActivityForResult(data, REQUEST_PICK_SHORTCUT2);
} else { } else {
if(mEventActionForPickNew) { if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick); mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
} }
@ -431,7 +434,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
if(mEventActionForPickNew) { if (mEventActionForPickNew) {
mEventActions.remove(mEventActionForPick); mEventActions.remove(mEventActionForPick);
mAdapter.notifyDataSetChanged(); 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 static class ActionsAdapter extends ArrayAdapter<Action> {
private final LayoutInflater mInflater; private final LayoutInflater mInflater;
private int mPrefLayout; private final int mPrefLayout;
private int mPrefCategoryLayout; private final int mPrefCategoryLayout;
public ActionsAdapter(Context context, ActionsDescription actionsDescription) { public ActionsAdapter(Context context, ActionsDescription actionsDescription) {
super(context, 0, filterActions(actionsDescription)); super(context, 0, filterActions(actionsDescription));
@ -508,7 +464,7 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
ArrayList<Action> filteredActions = new ArrayList<>(actions.size()); ArrayList<Action> filteredActions = new ArrayList<>(actions.size());
for (Action action : actions) { for (Action action : actions) {
if(action.action != GlobalConfig.UNSET) { if (action.action != GlobalConfig.UNSET) {
filteredActions.add(action); filteredActions.add(action);
} }
} }
@ -530,21 +486,68 @@ public class EventActionSetup extends ResourceWrapperActivity implements Adapter
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position); Action action = getItem(position);
boolean isCategory = action.action == GlobalConfig.CATEGORY; boolean isCategory = action.action == GlobalConfig.CATEGORY;
if(convertView == null) { if (convertView == null) {
convertView = mInflater.inflate(isCategory ? mPrefCategoryLayout : mPrefLayout, parent, false); 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); title_view.setText(action.label);
if(!isCategory) { if (!isCategory) {
title_view.setSingleLine(false); title_view.setSingleLine(false);
title_view.setMaxLines(2); title_view.setMaxLines(2);
convertView.findViewById(android.R.id.summary).setVisibility(View.GONE); convertView.findViewById(android.R.id.summary).setVisibility(View.GONE);
View icon = convertView.findViewById(android.R.id.icon); View icon = convertView.findViewById(android.R.id.icon);
if(icon != null) icon.setVisibility(View.GONE); if (icon != null) icon.setVisibility(View.GONE);
} }
return convertView; 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.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
@ -59,6 +58,12 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
private TextView mSelectionText; private TextView mSelectionText;
private CropperView mCropperView; 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 @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR); 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); 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; Bitmap bitmap;
Intent intent = getIntent(); Intent intent = getIntent();
String sourcePath = intent.getStringExtra(INTENT_EXTRA_IMAGE); String sourcePath = intent.getStringExtra(INTENT_EXTRA_IMAGE);
mSourceFile = new File(sourcePath); 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); bitmap = Utils.loadBitmap(mSourceFile, 0, 0, 0);
} else { } else {
bitmap = Utils.loadScreenSizedBitmap(getWindowManager(), sourcePath); bitmap = Utils.loadScreenSizedBitmap(getWindowManager(), sourcePath);
@ -87,16 +92,16 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
@Override @Override
public void onClick(View v) { public void onClick(View v) {
switch(v.getId()) { switch (v.getId()) {
case R.id.ok: case R.id.ok:
final Rect r = mCropperView.getSelection(); 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(); 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; boolean success;
// full image size: no cropping // full image size: no cropping
if(mSourceFile.compareTo(destinationFile) == 0) { if (mSourceFile.compareTo(destinationFile) == 0) {
// same file, nothing to do // same file, nothing to do
success = true; success = true;
} else { } else {
@ -159,7 +164,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
private void done(boolean success) { private void done(boolean success) {
setResult(success ? RESULT_OK : RESULT_CANCELED); setResult(success ? RESULT_OK : RESULT_CANCELED);
if(!success) { if (!success) {
Toast.makeText(this, R.string.tr_eu, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.tr_eu, Toast.LENGTH_SHORT).show();
} }
finish(); finish();
@ -167,7 +172,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
@Override @Override
public void onCropperViewSelectionChanged(Rect selection) { 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 @Override
@ -178,18 +183,18 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
View content = getLayoutInflater().inflate(R.layout.dialog_rect, null); View content = getLayoutInflater().inflate(R.layout.dialog_rect, null);
builder.setTitle(getString(R.string.rect)); builder.setTitle(getString(R.string.rect));
builder.setView(content); builder.setView(content);
((TextView)content.findViewById(R.id.rect_l)).setText(getString(R.string.left)); ((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_t)).setText(getString(R.string.top));
((TextView)content.findViewById(R.id.rect_r)).setText(getString(R.string.right)); ((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_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_w)).setText(getString(R.string.gb_w).toLowerCase());
((TextView)content.findViewById(R.id.rect_h)).setText(getString(R.string.gb_h).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 el = content.findViewById(R.id.rect_el);
final EditText et = (EditText)content.findViewById(R.id.rect_et); final EditText et = content.findViewById(R.id.rect_et);
final EditText er = (EditText)content.findViewById(R.id.rect_er); final EditText er = content.findViewById(R.id.rect_er);
final EditText eb = (EditText)content.findViewById(R.id.rect_eb); final EditText eb = content.findViewById(R.id.rect_eb);
final EditText ew = (EditText)content.findViewById(R.id.rect_ew); final EditText ew = content.findViewById(R.id.rect_ew);
final EditText eh = (EditText)content.findViewById(R.id.rect_eh); final EditText eh = content.findViewById(R.id.rect_eh);
el.setText(String.valueOf(selection.left)); el.setText(String.valueOf(selection.left));
et.setText(String.valueOf(selection.top)); et.setText(String.valueOf(selection.top));
er.setText(String.valueOf(selection.right)); 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 r = Integer.parseInt(er.getText().toString());
int w = Integer.parseInt(ew.getText().toString()); int w = Integer.parseInt(ew.getText().toString());
int new_w = r - l; int new_w = r - l;
if(new_w != w) { if (new_w != w) {
ew.setText(String.valueOf(new_w)); ew.setText(String.valueOf(new_w));
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -238,7 +243,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int b = Integer.parseInt(eb.getText().toString()); int b = Integer.parseInt(eb.getText().toString());
int h = Integer.parseInt(eh.getText().toString()); int h = Integer.parseInt(eh.getText().toString());
int new_h = b - t; int new_h = b - t;
if(new_h != h) { if (new_h != h) {
eh.setText(String.valueOf(new_h)); eh.setText(String.valueOf(new_h));
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -263,7 +268,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int r = Integer.parseInt(er.getText().toString()); int r = Integer.parseInt(er.getText().toString());
int w = Integer.parseInt(ew.getText().toString()); int w = Integer.parseInt(ew.getText().toString());
int new_r = l + w; int new_r = l + w;
if(new_r != r) { if (new_r != r) {
er.setText(String.valueOf(new_r)); er.setText(String.valueOf(new_r));
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -288,7 +293,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int h = Integer.parseInt(eh.getText().toString()); int h = Integer.parseInt(eh.getText().toString());
int b = Integer.parseInt(eb.getText().toString()); int b = Integer.parseInt(eb.getText().toString());
int new_b = t + h; int new_b = t + h;
if(new_b != b) { if (new_b != b) {
eb.setText(String.valueOf(new_b)); eb.setText(String.valueOf(new_b));
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -314,7 +319,7 @@ public class ImageCropper extends ResourceWrapperActivity implements View.OnClic
int b = Integer.parseInt(eb.getText().toString()); int b = Integer.parseInt(eb.getText().toString());
selection.set(l, t, r, b); selection.set(l, t, r, b);
mCropperView.setSelection(selection); 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.setNegativeButton(android.R.string.cancel, null);
builder.create().show(); 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; package net.pierrox.lightning_launcher.activities;
import static android.content.ClipData.newPlainText;
import android.Manifest; import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
@ -47,7 +49,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -88,8 +89,6 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; 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 { 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; private static final int MODE_NONE = -1;
@ -151,25 +150,21 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
private int mLauncherIconDensity; private int mLauncherIconDensity;
private View mClickedView; 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; 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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR); Utils.setTheme(this, Utils.APP_THEME_NO_ACTION_BAR);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if(savedInstanceState == null) { if (savedInstanceState == null) {
// if recreated because the activity has been disposed by the framework, don't remove // 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 // the temp file, it will be used for instance in the activity result callback
Utils.getTmpImageFile().delete(); Utils.getTmpImageFile().delete();
@ -191,14 +186,14 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
protected int sizeOf(String key, BitmapInfo bitmapInfo) { protected int sizeOf(String key, BitmapInfo bitmapInfo) {
// The cache size will be measured in kilobytes rather than // The cache size will be measured in kilobytes rather than
// number of items. // number of items.
if(finalGetByteCount != null) { if (finalGetByteCount != null) {
try { try {
return (Integer)finalGetByteCount.invoke(bitmapInfo.bitmap) / 1024; return (Integer) finalGetByteCount.invoke(bitmapInfo.bitmap) / 1024;
} catch (Exception e) { } catch (Exception e) {
// pass and continue // 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.setBounds(0, 0, mDefaultIcon.getWidth(), mDefaultIcon.getHeight());
d.draw(c); d.draw(c);
mStandardIconSize =getResources().getDimensionPixelSize(android.R.dimen.app_icon_size); mStandardIconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
mLauncherIconDensity =0; mLauncherIconDensity = 0;
try { try {
Method getLauncherLargeIconSize=ActivityManager.class.getMethod("getLauncherLargeIconSize"); Method getLauncherLargeIconSize = ActivityManager.class.getMethod("getLauncherLargeIconSize");
Method getLauncherLargeIconDensity=ActivityManager.class.getMethod("getLauncherLargeIconDensity"); Method getLauncherLargeIconDensity = ActivityManager.class.getMethod("getLauncherLargeIconDensity");
ActivityManager am=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
mStandardIconSize =(Integer) getLauncherLargeIconSize.invoke(am, (Object[])null); mStandardIconSize = (Integer) getLauncherLargeIconSize.invoke(am, (Object[]) null);
mLauncherIconDensity =(Integer) getLauncherLargeIconDensity.invoke(am, (Object[])null); mLauncherIconDensity = (Integer) getLauncherLargeIconDensity.invoke(am, (Object[]) null);
} catch (Exception e) { } catch (Exception e) {
// pass API level 11, 15 // 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); mCurrentScrollLauncherPage = prefs.getInt(PREF_CURRENT_SCROLL_LAUNCHER_PAGE, 0);
setContentView(R.layout.image_picker); 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)); 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); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSourceSpinner.setAdapter(adapter); mSourceSpinner.setAdapter(adapter);
mSourceSpinner.setOnItemSelectedListener(this); mSourceSpinner.setOnItemSelectedListener(this);
mIconPackSpinner = (Spinner) findViewById(R.id.icon_pack); mIconPackSpinner = findViewById(R.id.icon_pack);
mIconPackSpinner.setOnItemSelectedListener(this); mIconPackSpinner.setOnItemSelectedListener(this);
mPkgSpinner = (Spinner) findViewById(R.id.pkg); mPkgSpinner = findViewById(R.id.pkg);
mPkgSpinner.setOnItemSelectedListener(this); mPkgSpinner.setOnItemSelectedListener(this);
mLauncherPageSpinner = (Spinner) findViewById(R.id.launcher_page); mLauncherPageSpinner = findViewById(R.id.launcher_page);
mLauncherPageSpinner.setOnItemSelectedListener(this); mLauncherPageSpinner.setOnItemSelectedListener(this);
mPathTextGrp = findViewById(R.id.path_grp); mPathTextGrp = findViewById(R.id.path_grp);
mPathTextView = (TextView) findViewById(R.id.path); mPathTextView = findViewById(R.id.path);
Button up = (Button)findViewById(R.id.path_up); Button up = findViewById(R.id.path_up);
up.setText(R.string.file_picker_activity_up); up.setText(R.string.file_picker_activity_up);
up.setOnClickListener(this); up.setOnClickListener(this);
mNoIconTextView = (TextView) findViewById(R.id.no_icon); mNoIconTextView = findViewById(R.id.no_icon);
mNoIconTextView.setText(R.string.ip_e); mNoIconTextView.setText(R.string.ip_e);
mGridView = (GridView) findViewById(R.id.grid); mGridView = findViewById(R.id.grid);
mGridView.setNumColumns(GridView.AUTO_FIT); mGridView.setNumColumns(GridView.AUTO_FIT);
mGridView.setColumnWidth(mStandardIconSize * 2); mGridView.setColumnWidth(mStandardIconSize * 2);
mGridView.setStretchMode(GridView.STRETCH_SPACING_UNIFORM); 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); mBackgroundColor = prefs.getInt(PREF_BACKGROUND_COLOR, Color.TRANSPARENT);
mGridView.setBackgroundColor(mBackgroundColor); mGridView.setBackgroundColor(mBackgroundColor);
mSearchText = (EditTextIme) findViewById(R.id.search_text); mSearchText = findViewById(R.id.search_text);
mSearchText.setOnEditTextImeListener(this); mSearchText.setOnEditTextImeListener(this);
mSearchText.addTextChangedListener(this); mSearchText.addTextChangedListener(this);
@ -295,25 +288,25 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
Typeface typeface = LLApp.get().getIconsTypeface(); Typeface typeface = LLApp.get().getIconsTypeface();
int[] ids = new int[] { int[] ids = new int[]{
R.id.none, R.id.none,
R.id.ext_file, R.id.ext_file,
R.id.camera, R.id.camera,
R.id.bgcolor, R.id.bgcolor,
R.id.solid, R.id.solid,
R.id.search R.id.search
}; };
for(int id : ids) { for (int id : ids) {
View v = findViewById(id); View v = findViewById(id);
v.setOnClickListener(this); v.setOnClickListener(this);
v.setOnLongClickListener(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); mIconPackAdapter = new PkgLabelAdapter(this, true);
mIconPackSpinner.setAdapter(mIconPackAdapter); mIconPackSpinner.setAdapter(mIconPackAdapter);
if(mIconPackAdapter.getCount()==0) { if (mIconPackAdapter.getCount() == 0) {
mCurrentMode = MODE_PKG; mCurrentMode = MODE_PKG;
} }
} }
@ -324,14 +317,14 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
checkPermissions( checkPermissions(
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 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); REQUEST_PERMISSION_BASE);
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(areAllPermissionsGranted(grantResults, R.string.pr_f3)) { if (areAllPermissionsGranted(grantResults, R.string.pr_f3)) {
if(mCurrentMode == MODE_PATH) { if (mCurrentMode == MODE_PATH) {
setMode(MODE_PATH); setMode(MODE_PATH);
} }
} }
@ -364,18 +357,18 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
// if(init == null) { // if(init == null) {
// adapterView.setTag(true); // adapterView.setTag(true);
// } else { // } else {
if (adapterView == mSourceSpinner) { if (adapterView == mSourceSpinner) {
setMode(i); setMode(i);
} else if (adapterView == mIconPackSpinner) { } else if (adapterView == mIconPackSpinner) {
String pkg = mIconPackAdapter.getItem(i).pkg; String pkg = mIconPackAdapter.getItem(i).pkg;
loadIconPack(pkg); loadIconPack(pkg);
} else if (adapterView == mPkgSpinner) { } else if (adapterView == mPkgSpinner) {
String pkg = mPkgAdapter.getItem(i).pkg; String pkg = mPkgAdapter.getItem(i).pkg;
loadPkg(pkg); loadPkg(pkg);
} else if (adapterView == mLauncherPageSpinner) { } else if (adapterView == mLauncherPageSpinner) {
String p = mLauncherPageAdapter.getItem(i); String p = mLauncherPageAdapter.getItem(i);
loadLauncherPage(p); loadLauncherPage(p);
} }
// } // }
} }
@ -386,50 +379,50 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
if(adapterView == mGridView) { if (adapterView == mGridView) {
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
Object item = mGridView.getItemAtPosition(position); Object item = mGridView.getItemAtPosition(position);
File tmp_image_file = Utils.getTmpImageFile(); File tmp_image_file = Utils.getTmpImageFile();
if(mCurrentMode == MODE_PATH) { if (mCurrentMode == MODE_PATH) {
ImageFile imf = (ImageFile) item; ImageFile imf = (ImageFile) item;
if(imf.file.isDirectory()) { if (imf.file.isDirectory()) {
loadPath(imf.file); loadPath(imf.file);
} else { } else {
Utils.copyFileSafe(buffer, imf.file, tmp_image_file); Utils.copyFileSafe(buffer, imf.file, tmp_image_file);
imagePicked(true); imagePicked(true);
} }
} else if(mCurrentMode == MODE_PKG || mCurrentMode == MODE_ICON_PACK) { } else if (mCurrentMode == MODE_PKG || mCurrentMode == MODE_ICON_PACK) {
ImageResource ir = (ImageResource) item; ImageResource ir = (ImageResource) item;
FileOutputStream fos=null; FileOutputStream fos = null;
InputStream is = null; InputStream is = null;
try { try {
Resources rsrc = ir.packageName.equals(ANDROID) ? getResources() : createPackageContext(ir.packageName, 0).getResources(); Resources rsrc = ir.packageName.equals(ANDROID) ? getResources() : createPackageContext(ir.packageName, 0).getResources();
int id = ir.res; int id = ir.res;
boolean is_nine_patch = false; boolean is_nine_patch = false;
Bitmap bmp = null; Bitmap bmp = null;
if(Utils.sGetDrawableForDensity!=null) { if (Utils.sGetDrawableForDensity != null) {
try { try {
BitmapDrawable d=(BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity); BitmapDrawable d = (BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity);
Bitmap orig_bmp = d.getBitmap(); Bitmap orig_bmp = d.getBitmap();
is_nine_patch = NinePatch.isNinePatchChunk(orig_bmp.getNinePatchChunk()); is_nine_patch = NinePatch.isNinePatchChunk(orig_bmp.getNinePatchChunk());
bmp = Utils.createStandardSizedIcon(orig_bmp, mStandardIconSize); bmp = Utils.createStandardSizedIcon(orig_bmp, mStandardIconSize);
} catch(Throwable e) { } catch (Throwable e) {
// pass, continue with classic method // pass, continue with classic method
} }
} }
if(bmp == null) { if (bmp == null) {
bmp = BitmapFactory.decodeResource(rsrc, id); bmp = BitmapFactory.decodeResource(rsrc, id);
if(bmp != null) { if (bmp != null) {
is_nine_patch = NinePatch.isNinePatchChunk(bmp.getNinePatchChunk()); is_nine_patch = NinePatch.isNinePatchChunk(bmp.getNinePatchChunk());
} }
} }
if(bmp != null) { if (bmp != null) {
if(is_nine_patch) { if (is_nine_patch) {
// nine patches need to be copied as is // nine patches need to be copied as is
is = rsrc.openRawResource(ir.res); is = rsrc.openRawResource(ir.res);
fos=new FileOutputStream(tmp_image_file); fos = new FileOutputStream(tmp_image_file);
int n; int n;
while((n=is.read(buffer))>0) { while ((n = is.read(buffer)) > 0) {
fos.write(buffer, 0, n); fos.write(buffer, 0, n);
} }
} else { } else {
@ -445,10 +438,16 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
e.printStackTrace(); e.printStackTrace();
tmp_image_file.delete(); tmp_image_file.delete();
} finally { } finally {
if(is!=null) try { is.close(); } catch(Exception e) {} if (is != null) try {
if(fos!=null) try { fos.close(); } catch(Exception e) {} 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; ImageFile imf = (ImageFile) item;
Utils.copyFileSafe(buffer, imf.file, tmp_image_file); Utils.copyFileSafe(buffer, imf.file, tmp_image_file);
imagePicked(true); imagePicked(true);
@ -461,15 +460,15 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
String label; String label;
String clip_text; String clip_text;
Object item = adapterView.getItemAtPosition(i); 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; ImageFile f = (ImageFile) item;
label = f.file.getAbsolutePath(); label = f.file.getAbsolutePath();
clip_text = label; clip_text = label;
} else { } else {
ImageResource pkg = (ImageResource) item; ImageResource pkg = (ImageResource) item;
String s = pkg.packageName.equals(ANDROID) ? "android" : pkg.packageName; String s = pkg.packageName.equals(ANDROID) ? "android" : pkg.packageName;
label = s+"/"+pkg.label; label = s + "/" + pkg.label;
clip_text = "\""+s+"\", \""+pkg.label+"\""; clip_text = "\"" + s + "\", \"" + pkg.label + "\"";
} }
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = newPlainText("llx", clip_text); ClipData clip = newPlainText("llx", clip_text);
@ -487,7 +486,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
mClickedView = view; mClickedView = view;
final int id = view.getId(); final int id = view.getId();
switch(id) { switch (id) {
case R.id.none: case R.id.none:
Utils.getTmpImageFile().delete(); Utils.getTmpImageFile().delete();
imagePicked(false); imagePicked(false);
@ -512,7 +511,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
case R.id.bgcolor: case R.id.bgcolor:
case R.id.solid: 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.setAlphaSliderVisible(true);
color_picker_dialog.setOnColorChangedListener(this); color_picker_dialog.setOnColorChangedListener(this);
color_picker_dialog.show(); color_picker_dialog.show();
@ -524,7 +523,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
case R.id.path_up: case R.id.path_up:
File parent = mCurrentPath.getParentFile(); File parent = mCurrentPath.getParentFile();
if(parent != null) { if (parent != null) {
loadPath(parent); loadPath(parent);
} }
break; break;
@ -535,13 +534,25 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
int label_res = 0; int label_res = 0;
switch(view.getId()) { switch (view.getId()) {
case R.id.none: label_res = R.string.ip_none; break; case R.id.none:
case R.id.ext_file: label_res = R.string.ip_ext_file; break; label_res = R.string.ip_none;
case R.id.camera: label_res = R.string.ip_camera; break; break;
case R.id.bgcolor: label_res = R.string.ip_bgcolor; break; case R.id.ext_file:
case R.id.solid: label_res = R.string.ip_solid; break; label_res = R.string.ip_ext_file;
case R.id.search: label_res = R.string.ip_search; break; 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(); Toast.makeText(this, label_res, Toast.LENGTH_SHORT).show();
return true; return true;
@ -551,13 +562,13 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case REQUEST_CAPTURE_IMAGE: case REQUEST_CAPTURE_IMAGE:
if(resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
imagePicked(true); imagePicked(true);
} }
break; break;
case REQUEST_PICK_IMAGE: case REQUEST_PICK_IMAGE:
if(resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
FileOutputStream fos = null; FileOutputStream fos = null;
InputStream is = null; InputStream is = null;
try { try {
@ -565,21 +576,27 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
is = getContentResolver().openInputStream(data.getData()); is = getContentResolver().openInputStream(data.getData());
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
int n; int n;
while((n=is.read(buffer))>0) { while ((n = is.read(buffer)) > 0) {
fos.write(buffer, 0, n); fos.write(buffer, 0, n);
} }
imagePicked(true); imagePicked(true);
} catch(IOException e) { } catch (IOException e) {
// pass // pass
} finally { } finally {
if(fos != null) try { fos.close(); } catch(IOException e) {} if (fos != null) try {
if(is != null) try { is.close(); } catch(IOException e) {} fos.close();
} catch (IOException e) {
}
if (is != null) try {
is.close();
} catch (IOException e) {
}
} }
} }
break; break;
case REQUEST_CROP_IMAGE: case REQUEST_CROP_IMAGE:
if(resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
setResult(RESULT_OK); setResult(RESULT_OK);
finish(); 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) { private void setGridViewAdapter(ListAdapter adapter) {
mNoIconTextView.setVisibility(adapter == null || adapter.getCount() == 0 ? View.VISIBLE : View.GONE); mNoIconTextView.setVisibility(adapter == null || adapter.getCount() == 0 ? View.VISIBLE : View.GONE);
mGridView.setAdapter(adapter); mGridView.setAdapter(adapter);
@ -609,25 +620,25 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
boolean launcher_page = false; boolean launcher_page = false;
int pos = 0; int pos = 0;
int count; int count;
switch(mode) { switch (mode) {
case MODE_ICON_PACK: case MODE_ICON_PACK:
icon_pack = true; icon_pack = true;
if(mIconPackAdapter == null) { if (mIconPackAdapter == null) {
mIconPackAdapter = new PkgLabelAdapter(this, true); mIconPackAdapter = new PkgLabelAdapter(this, true);
mIconPackSpinner.setAdapter(mIconPackAdapter); mIconPackSpinner.setAdapter(mIconPackAdapter);
} }
if(mIconPackAdapter.getCount() == 0) { if (mIconPackAdapter.getCount() == 0) {
setGridViewAdapter(null); setGridViewAdapter(null);
} }
count = mIconPackAdapter.getCount(); count = mIconPackAdapter.getCount();
for(int i=0; i<count; i++) { for (int i = 0; i < count; i++) {
if(mIconPackAdapter.getItem(i).pkg.equals(mCurrentIconPack)) { if (mIconPackAdapter.getItem(i).pkg.equals(mCurrentIconPack)) {
pos = i; pos = i;
break; break;
} }
} }
if(mIconPackSpinner.getSelectedItemPosition() != pos) { if (mIconPackSpinner.getSelectedItemPosition() != pos) {
mIconPackSpinner.setSelection(pos); mIconPackSpinner.setSelection(pos);
} else { } else {
loadIconPack(mCurrentIconPack); loadIconPack(mCurrentIconPack);
@ -643,17 +654,17 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
launcher_page = true; launcher_page = true;
File base_dir = LLApp.get().getAppEngine().getBaseDir(); File base_dir = LLApp.get().getAppEngine().getBaseDir();
ArrayList<String> pages = new ArrayList<String>(); ArrayList<String> pages = new ArrayList<String>();
if(mLauncherPageAdapter == null) { if (mLauncherPageAdapter == null) {
for(int p = Page.FIRST_DASHBOARD_PAGE; p< Page.LAST_DASHBOARD_PAGE; p++) { for (int p = Page.FIRST_DASHBOARD_PAGE; p < Page.LAST_DASHBOARD_PAGE; p++) {
File f = Page.getIconDir(base_dir, p); File f = Page.getIconDir(base_dir, p);
if(f.exists()) { if (f.exists()) {
pages.add(String.valueOf(p)); pages.add(String.valueOf(p));
} }
} }
pages.add(String.valueOf(Page.APP_DRAWER_PAGE)); 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); File f = Page.getIconDir(base_dir, p);
if(f.exists()) { if (f.exists()) {
pages.add(String.valueOf(p)); pages.add(String.valueOf(p));
} }
} }
@ -663,14 +674,14 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} }
count = mLauncherPageAdapter.getCount(); count = mLauncherPageAdapter.getCount();
for(int i=0; i<count; i++) { for (int i = 0; i < count; i++) {
if(mLauncherPageAdapter.getItem(i).equals(mCurrentLauncherPage)) { if (mLauncherPageAdapter.getItem(i).equals(mCurrentLauncherPage)) {
pos = i; pos = i;
break; break;
} }
} }
if(mLauncherPageSpinner.getSelectedItemPosition() != pos) { if (mLauncherPageSpinner.getSelectedItemPosition() != pos) {
mLauncherPageSpinner.setSelection(pos); mLauncherPageSpinner.setSelection(pos);
} else { } else {
loadLauncherPage(mCurrentLauncherPage); loadLauncherPage(mCurrentLauncherPage);
@ -680,18 +691,18 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
case MODE_PKG: case MODE_PKG:
pkg = true; pkg = true;
if(mPkgAdapter == null) { if (mPkgAdapter == null) {
mPkgAdapter = new PkgLabelAdapter(this, false); mPkgAdapter = new PkgLabelAdapter(this, false);
mPkgSpinner.setAdapter(mPkgAdapter); mPkgSpinner.setAdapter(mPkgAdapter);
} }
count = mPkgAdapter.getCount(); count = mPkgAdapter.getCount();
for(int i=0; i<count; i++) { for (int i = 0; i < count; i++) {
if(mPkgAdapter.getItem(i).pkg.equals(mCurrentPkg)) { if (mPkgAdapter.getItem(i).pkg.equals(mCurrentPkg)) {
pos = i; pos = i;
break; break;
} }
} }
if(mPkgSpinner.getSelectedItemPosition() != pos) { if (mPkgSpinner.getSelectedItemPosition() != pos) {
mPkgSpinner.setSelection(pos); mPkgSpinner.setSelection(pos);
} else { } else {
loadPkg(mCurrentPkg); loadPkg(mCurrentPkg);
@ -725,7 +736,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
File[] files = path.listFiles(); File[] files = path.listFiles();
if(files != null) { if (files != null) {
for (File f : files) { for (File f : files) {
if (f.isDirectory()) { if (f.isDirectory()) {
images.add(new ImageFile(f)); images.add(new ImageFile(f));
@ -805,8 +816,8 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
ArrayList<ImageResource> pkgs = new ArrayList<ImageResource>(); ArrayList<ImageResource> pkgs = new ArrayList<ImageResource>();
Resources rsrc = remoteContext.getResources(); Resources rsrc = remoteContext.getResources();
int start = isAndroidPackage ? 0x01080000 : 0x7f020000; int start = isAndroidPackage ? 0x01080000 : 0x7f020000;
int end = start+0x1000; int end = start + 0x1000;
for(int i=start; i<end; i++) { for (int i = start; i < end; i++) {
try { try {
String label = rsrc.getResourceEntryName(i); String label = rsrc.getResourceEntryName(i);
@ -815,7 +826,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
ir.label = label; ir.label = label;
ir.res = i; ir.res = i;
pkgs.add(ir); pkgs.add(ir);
} catch(Resources.NotFoundException e) { } catch (Resources.NotFoundException e) {
break; break;
} }
} }
@ -831,7 +842,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} }
private void storeGridViewScroll() { private void storeGridViewScroll() {
if(mGridMode != MODE_NONE) { if (mGridMode != MODE_NONE) {
int offset = mStandardIconSize / 3; int offset = mStandardIconSize / 3;
int index = mCurrentScrollIndex;//mGridView.getFirstVisiblePosition(); int index = mCurrentScrollIndex;//mGridView.getFirstVisiblePosition();
final View first = mGridView.getChildAt(0); final View first = mGridView.getChildAt(0);
@ -839,19 +850,27 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
offset -= first.getTop(); offset -= first.getTop();
} }
int y = (index<<16) | offset; int y = (index << 16) | offset;
switch (mGridMode) { switch (mGridMode) {
case MODE_PKG: mCurrentScrollPkg = y; break; case MODE_PKG:
case MODE_PATH: mCurrentScrollPath = y; break; mCurrentScrollPkg = y;
case MODE_ICON_PACK: mCurrentScrollIconPack = y; break; break;
case MODE_LAUNCHER_PAGE: mCurrentScrollLauncherPage = 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) { private void setGridViewScroll(int scroll) {
if(mGridMode == mCurrentMode) { if (mGridMode == mCurrentMode) {
mGridView.setSelection(0); mGridView.setSelection(0);
} else { } else {
mGridMode = mCurrentMode; mGridMode = mCurrentMode;
@ -862,7 +881,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public void onColorChanged(int color) { public void onColorChanged(int color) {
switch(mClickedView.getId()) { switch (mClickedView.getId()) {
case R.id.solid: case R.id.solid:
Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
b.eraseColor(color); b.eraseColor(color);
@ -874,7 +893,10 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} finally { } 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) { private void imagePicked(boolean allow_crop) {
// if(getIntent().getBooleanExtra(INTENT_EXTRA_CROP, false) && allow_crop) { // if(getIntent().getBooleanExtra(INTENT_EXTRA_CROP, false) && allow_crop) {
File file = Utils.getTmpImageFile(); File file = Utils.getTmpImageFile();
if(allow_crop) { if (allow_crop) {
if(Utils.isSvgFile(file)) { if (Utils.isSvgFile(file)) {
allow_crop = false; allow_crop = false;
} }
} }
if(allow_crop) { if (allow_crop) {
ImageCropper.startActivity(this, file, REQUEST_CROP_IMAGE); ImageCropper.startActivity(this, file, REQUEST_CROP_IMAGE);
} else { } else {
setResult(RESULT_OK); setResult(RESULT_OK);
@ -916,9 +938,9 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} }
private void setSearchMode(boolean on) { 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); View src_grp = findViewById(R.id.src_grp);
if(on) { if (on) {
mSearchText.setVisibility(View.VISIBLE); mSearchText.setVisibility(View.VISIBLE);
mSearchText.setText(""); mSearchText.setText("");
mSearchText.requestFocus(); mSearchText.requestFocus();
@ -947,7 +969,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
ArrayAdapter<?> adapter = (ArrayAdapter<?>) mGridView.getAdapter(); ArrayAdapter<?> adapter = (ArrayAdapter<?>) mGridView.getAdapter();
if(adapter != null) { if (adapter != null) {
adapter.getFilter().filter(s.toString()); 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 { private static class PkgLabel {
String pkg; String pkg;
String label; 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 abstract class MyFilterArrayAdapter<T> extends ArrayAdapter<T> {
private final Object mLock = new Object();
private Filter mFilter; private Filter mFilter;
private List<T> mOriginalItems; private List<T> mOriginalItems;
private List<T> mItems; private List<T> mItems;
private final Object mLock = new Object();
public MyFilterArrayAdapter(Context context, int resource) { public MyFilterArrayAdapter(Context context, int resource) {
@ -1065,9 +1138,6 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} }
} }
private class PkgLabelAdapter extends MyFilterArrayAdapter<PkgLabel> { private class PkgLabelAdapter extends MyFilterArrayAdapter<PkgLabel> {
public PkgLabelAdapter(Context context, boolean icon) { public PkgLabelAdapter(Context context, boolean icon) {
@ -1076,20 +1146,20 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
PackageManager pm = getPackageManager(); PackageManager pm = getPackageManager();
ArrayList<PkgLabel> items = new ArrayList<PkgLabel>(); ArrayList<PkgLabel> items = new ArrayList<PkgLabel>();
if(icon) { if (icon) {
String myPackagename = getPackageName(); String myPackagename = getPackageName();
Intent filter = new Intent("org.adw.launcher.icons.ACTION_PICK_ICON"); Intent filter = new Intent("org.adw.launcher.icons.ACTION_PICK_ICON");
List<ResolveInfo> ris = pm.queryIntentActivities(filter, 0); List<ResolveInfo> ris = pm.queryIntentActivities(filter, 0);
for (ResolveInfo ri : ris) { for (ResolveInfo ri : ris) {
String packageName = ri.activityInfo.packageName; String packageName = ri.activityInfo.packageName;
if(!myPackagename.equals(packageName)) { if (!myPackagename.equals(packageName)) {
PkgLabel pkg = new PkgLabel(packageName, ri.loadLabel(pm).toString()); PkgLabel pkg = new PkgLabel(packageName, ri.loadLabel(pm).toString());
items.add(pkg); items.add(pkg);
} }
} }
} else { } else {
List<PackageInfo> pis = pm.getInstalledPackages(0); 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()); PkgLabel pkg = new PkgLabel(pi.packageName, pi.applicationInfo.loadLabel(pm).toString());
items.add(pkg); items.add(pkg);
} }
@ -1100,7 +1170,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
return Utils.sItemNameCollator.compare(pkg1.label, pkg2.label); return Utils.sItemNameCollator.compare(pkg1.label, pkg2.label);
} }
}); });
if(!icon) { if (!icon) {
PkgLabel android_pkg = new PkgLabel(ANDROID, "Android"); PkgLabel android_pkg = new PkgLabel(ANDROID, "Android");
items.add(0, android_pkg); items.add(0, android_pkg);
} }
@ -1111,42 +1181,30 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { 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); 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; return convertView;
} }
@Override @Override
public View getDropDownView(int position, View convertView, ViewGroup parent) { 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); 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; 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 class ImageResourceAdapter extends MyFilterArrayAdapter<ImageResource> {
private boolean mDisplayLabels; private final boolean mDisplayLabels;
public ImageResourceAdapter(Context context, int resource, List<ImageResource> objects, boolean display_labels) { public ImageResourceAdapter(Context context, int resource, List<ImageResource> objects, boolean display_labels) {
super(context, resource); super(context, resource);
@ -1158,23 +1216,23 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) { if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.item, null); convertView = getLayoutInflater().inflate(R.layout.item, null);
} }
final ImageResource ir = getItem(position); final ImageResource ir = getItem(position);
final TextView title = (TextView) convertView.findViewById(R.id.label); final TextView title = convertView.findViewById(R.id.label);
final ImageView thumbnail = (ImageView) convertView.findViewById(R.id.icon); final ImageView thumbnail = convertView.findViewById(R.id.icon);
if(mDisplayLabels) { if (mDisplayLabels) {
title.setText(ir.label); title.setText(ir.label);
title.setVisibility(View.VISIBLE); title.setVisibility(View.VISIBLE);
} else { } else {
title.setVisibility(View.GONE); title.setVisibility(View.GONE);
} }
BitmapInfo bitmap_info = mThumbnailCache.get(ir.packageName+ir.res); BitmapInfo bitmap_info = mThumbnailCache.get(ir.packageName + ir.res);
if(bitmap_info != null) { if (bitmap_info != null) {
Bitmap bitmap = bitmap_info.bitmap; Bitmap bitmap = bitmap_info.bitmap;
thumbnail.setImageBitmap(bitmap); thumbnail.setImageBitmap(bitmap);
title.setTypeface(null, bitmap_info.isNinePatch ? Typeface.BOLD_ITALIC : Typeface.NORMAL); title.setTypeface(null, bitmap_info.isNinePatch ? Typeface.BOLD_ITALIC : Typeface.NORMAL);
@ -1182,7 +1240,7 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
} else { } else {
thumbnail.setTag(ir); thumbnail.setTag(ir);
thumbnail.setImageBitmap(null); thumbnail.setImageBitmap(null);
new AsyncTask<ImageResource,Void,Bitmap>() { new AsyncTask<ImageResource, Void, Bitmap>() {
private ImageResource mPackage; private ImageResource mPackage;
private boolean mIsNinePatch; private boolean mIsNinePatch;
@ -1195,36 +1253,36 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
String pkg_name = ir.packageName; String pkg_name = ir.packageName;
Resources rsrc = pkg_name.equals(ANDROID) ? getResources() : createPackageContext(pkg_name, 0).getResources(); Resources rsrc = pkg_name.equals(ANDROID) ? getResources() : createPackageContext(pkg_name, 0).getResources();
mIsNinePatch = false; mIsNinePatch = false;
if(Utils.sGetDrawableForDensity!=null) { if (Utils.sGetDrawableForDensity != null) {
try { try {
BitmapDrawable d=(BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity); BitmapDrawable d = (BitmapDrawable) Utils.sGetDrawableForDensity.invoke(rsrc, id, mLauncherIconDensity);
Bitmap orig_bmp = d.getBitmap(); Bitmap orig_bmp = d.getBitmap();
mIsNinePatch = NinePatch.isNinePatchChunk(orig_bmp.getNinePatchChunk()); mIsNinePatch = NinePatch.isNinePatchChunk(orig_bmp.getNinePatchChunk());
bmp = Utils.createStandardSizedIcon(orig_bmp, mStandardIconSize); bmp = Utils.createStandardSizedIcon(orig_bmp, mStandardIconSize);
} catch(Throwable e) { } catch (Throwable e) {
// pass, continue with classic method // pass, continue with classic method
} }
} }
if(bmp == null) { if (bmp == null) {
bmp = BitmapFactory.decodeResource(rsrc, id); bmp = BitmapFactory.decodeResource(rsrc, id);
if(bmp != null) { if (bmp != null) {
mIsNinePatch = NinePatch.isNinePatchChunk(bmp.getNinePatchChunk()); mIsNinePatch = NinePatch.isNinePatchChunk(bmp.getNinePatchChunk());
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
if(bmp == null) { if (bmp == null) {
bmp = mDefaultIcon; bmp = mDefaultIcon;
} }
mThumbnailCache.put(ir.packageName+ir.res, new BitmapInfo(bmp, mIsNinePatch)); mThumbnailCache.put(ir.packageName + ir.res, new BitmapInfo(bmp, mIsNinePatch));
return bmp; return bmp;
} }
@Override @Override
protected void onPostExecute(Bitmap bmp) { protected void onPostExecute(Bitmap bmp) {
if(thumbnail.getTag() == mPackage) { if (thumbnail.getTag() == mPackage) {
thumbnail.setImageBitmap(bmp); thumbnail.setImageBitmap(bmp);
title.setTypeface(null, mIsNinePatch ? Typeface.BOLD_ITALIC : Typeface.NORMAL); 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 class ImageFileAdapter extends MyFilterArrayAdapter<ImageFile> {
private boolean mDisplayLabels; private final boolean mDisplayLabels;
private Bitmap mFolderIcon; private final Bitmap mFolderIcon;
public ImageFileAdapter(Context context, int resource, List<ImageFile> objects, boolean display_labels) { public ImageFileAdapter(Context context, int resource, List<ImageFile> objects, boolean display_labels) {
super(context, resource); super(context, resource);
mDisplayLabels = display_labels; mDisplayLabels = display_labels;
int[] textSizeAttr = new int[] { android.R.attr.colorForeground }; int[] textSizeAttr = new int[]{android.R.attr.colorForeground};
TypedArray a = context.obtainStyledAttributes(textSizeAttr); TypedArray a = context.obtainStyledAttributes(textSizeAttr);
mFolderIcon = Utils.createIconFromText(Utils.getStandardIconSize(), "f", a.getColor(0, 0)); mFolderIcon = Utils.createIconFromText(Utils.getStandardIconSize(), "f", a.getColor(0, 0));
@ -1268,22 +1313,22 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) { if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.item, null); convertView = getLayoutInflater().inflate(R.layout.item, null);
} }
final ImageFile imf = getItem(position); final ImageFile imf = getItem(position);
final TextView title = (TextView) convertView.findViewById(R.id.label); final TextView title = convertView.findViewById(R.id.label);
final ImageView thumbnail = (ImageView) convertView.findViewById(R.id.icon); final ImageView thumbnail = convertView.findViewById(R.id.icon);
if(mDisplayLabels) { if (mDisplayLabels) {
title.setText(imf.file.getName()); title.setText(imf.file.getName());
title.setVisibility(View.VISIBLE); title.setVisibility(View.VISIBLE);
} else { } else {
title.setVisibility(View.GONE); title.setVisibility(View.GONE);
} }
if(imf.file.isDirectory()) { if (imf.file.isDirectory()) {
thumbnail.setImageBitmap(mFolderIcon); thumbnail.setImageBitmap(mFolderIcon);
} else { } else {
BitmapInfo bitmap_info = mThumbnailCache.get(imf.file.getAbsolutePath()); BitmapInfo bitmap_info = mThumbnailCache.get(imf.file.getAbsolutePath());
@ -1335,21 +1380,4 @@ public class ImagePicker extends ResourceWrapperActivity implements AdapterView.
// return mDisplayLabels; // 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.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import net.pierrox.lightning_launcher.LLApp; import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity; import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig; import net.pierrox.lightning_launcher.configuration.GlobalConfig;
@ -56,8 +56,8 @@ import java.util.List;
import java.util.Stack; import java.util.Stack;
public class LockScreen extends Dashboard { 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 LockScreen sThis;
public static Integer sMyTaskId; public static Integer sMyTaskId;
@ -77,10 +77,10 @@ public class LockScreen extends Dashboard {
mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(2); List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(2);
int size = tasks.size(); int size = tasks.size();
if(size > 0) { if (size > 0) {
sMyTaskId = tasks.get(0).id; sMyTaskId = tasks.get(0).id;
} }
if(size == 2) { if (size == 2) {
mLastTaskId = tasks.get(1).id; mLastTaskId = tasks.get(1).id;
} else { } else {
mLastTaskId = null; mLastTaskId = null;
@ -113,19 +113,16 @@ public class LockScreen extends Dashboard {
} }
try { try {
Method getActionBar=getClass().getMethod("getActionBar"); Method getActionBar = getClass().getMethod("getActionBar");
Object action_bar=getActionBar.invoke(this, (Object[])null); Object action_bar = getActionBar.invoke(this, (Object[]) null);
action_bar.getClass().getMethod("hide").invoke(action_bar, (Object[])null); action_bar.getClass().getMethod("hide").invoke(action_bar, (Object[]) null);
} catch(Exception e) { } catch (Exception e) {
// pass, API level 11 // pass, API level 11
} }
mNavigationStack = new Stack<Integer>();
mNavigationStack=new Stack<Integer>();
LLApp llApp = LLApp.get(); LLApp llApp = LLApp.get();
LightningEngine engine = llApp.getAppEngine(); LightningEngine engine = llApp.getAppEngine();
@ -133,13 +130,13 @@ public class LockScreen extends Dashboard {
int lockScreen = globalConfig.lockScreen; int lockScreen = globalConfig.lockScreen;
mLockScreenPage = engine.getOrLoadPage(lockScreen); mLockScreenPage = engine.getOrLoadPage(lockScreen);
mItemLayout=(ItemLayout)findViewById(R.id.drawer_il); mItemLayout = findViewById(R.id.drawer_il);
mScreen.takeItemLayoutOwnership(mItemLayout); mScreen.takeItemLayoutOwnership(mItemLayout);
mItemLayout.setHonourFocusChange(false); mItemLayout.setHonourFocusChange(false);
mItemLayout.setPage(mLockScreenPage); mItemLayout.setPage(mLockScreenPage);
configureActivity(mLockScreenPage); configureActivity(mLockScreenPage);
if(globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) { if (globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) {
stopService(llApp.getWindowServiceIntent()); stopService(llApp.getWindowServiceIntent());
} }
@ -159,7 +156,7 @@ public class LockScreen extends Dashboard {
@Override @Override
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
mScreen.zoomToOrigin(mScreen.getTargetOrTopmostItemLayout()); mScreen.zoomToOrigin(mScreen.getTargetOrTopmostItemLayout());
return true; return true;
} }
@ -197,9 +194,12 @@ public class LockScreen extends Dashboard {
@Override @Override
public void onShow(DialogInterface dialogInterface) { public void onShow(DialogInterface dialogInterface) {
finish(); finish();
try { removeDialog(DIALOG_UNLOCK); } catch(Exception e) {} try {
if(mRestorePreviousTask) { removeDialog(DIALOG_UNLOCK);
if(mLastTaskId != null) { } catch (Exception e) {
}
if (mRestorePreviousTask) {
if (mLastTaskId != null) {
try { try {
mMoveTaskToFront.invoke(mActivityManager, mLastTaskId, 0); mMoveTaskToFront.invoke(mActivityManager, mLastTaskId, 0);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
@ -207,7 +207,7 @@ public class LockScreen extends Dashboard {
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
if(mNeedDashboardRestart) { if (mNeedDashboardRestart) {
Intent intent = new Intent(LockScreen.this, Dashboard.class); Intent intent = new Intent(LockScreen.this, Dashboard.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent); startActivity(intent);
@ -220,15 +220,17 @@ public class LockScreen extends Dashboard {
} }
public void unlock(boolean restore_previous_task) { public void unlock(boolean restore_previous_task) {
mRestorePreviousTask = 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); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
LLApp llApp = LLApp.get(); LLApp llApp = LLApp.get();
GlobalConfig globalConfig = llApp.getAppEngine().getGlobalConfig(); GlobalConfig globalConfig = llApp.getAppEngine().getGlobalConfig();
if(globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) { if (globalConfig.overlayScreen != Page.NONE && globalConfig.lockDisableOverlay) {
startService(llApp.getWindowServiceIntent()); startService(llApp.getWindowServiceIntent());
} }
Intent unlocked = new Intent(Dashboard.BROADCAST_ACTION_UNLOCKED); Intent unlocked = new Intent(Dashboard.BROADCAST_ACTION_UNLOCKED);
@ -250,7 +252,7 @@ public class LockScreen extends Dashboard {
@Override @Override
public void onWidgetClicked() { public void onWidgetClicked() {
if(mGlobalConfig.launchUnlock) { if (mGlobalConfig.launchUnlock) {
mItemLayout.postDelayed(new Runnable() { mItemLayout.postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -262,7 +264,7 @@ public class LockScreen extends Dashboard {
@Override @Override
public ItemLayout loadRootItemLayout(int page, boolean reset_navigation_history, boolean displayImmediately, boolean animate) { 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; return mItemLayout;
} else { } else {
return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate); return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate);
@ -297,7 +299,7 @@ public class LockScreen extends Dashboard {
@Override @Override
protected void launchIntent(Intent intent, ItemView itemView) { protected void launchIntent(Intent intent, ItemView itemView) {
super.launchIntent(intent, itemView); super.launchIntent(intent, itemView);
if(mGlobalConfig.launchUnlock) { if (mGlobalConfig.launchUnlock) {
unlock(false); unlock(false);
} }
} }

View file

@ -47,14 +47,48 @@ import net.pierrox.lightning_launcher.util.SetVariableDialog;
import net.pierrox.lightning_launcher_extreme.R; import net.pierrox.lightning_launcher_extreme.R;
public class Shortcuts extends ResourceWrapperListActivity { public class Shortcuts extends ResourceWrapperListActivity {
private static final String INDENT = " "; private static final String INDENT = " ";
private String[] mItems; private String[] mItems;
private boolean mIsForTaskerScript; private boolean mIsForTaskerScript;
private boolean mIsForTaskerVariable; 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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
final Intent intent = getIntent(); final Intent intent = getIntent();
String className = intent.getComponent().getClassName(); String className = intent.getComponent().getClassName();
mIsForTaskerScript = className.endsWith("TS"); mIsForTaskerScript = className.endsWith("TS");
@ -62,14 +96,12 @@ public class Shortcuts extends ResourceWrapperListActivity {
Utils.setTheme(this, mIsForTaskerScript ? Utils.APP_THEME_TRANSLUCENT : Utils.APP_THEME); Utils.setTheme(this, mIsForTaskerScript ? Utils.APP_THEME_TRANSLUCENT : Utils.APP_THEME);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if(mIsForTaskerScript) { if (mIsForTaskerScript) {
pickScriptAndCreateShortcut(); pickScriptAndCreateShortcut();
return; } else if (mIsForTaskerVariable) {
} else if(mIsForTaskerVariable) {
pickVariableAndCreateShortcut(); pickVariableAndCreateShortcut();
return;
} else { } else {
mItems = new String[]{ mItems = new String[]{
getString(R.string.settings), // 0 getString(R.string.settings), // 0
@ -110,11 +142,11 @@ public class Shortcuts extends ResourceWrapperListActivity {
} }
} }
@Override @Override
protected void onListItemClick(ListView l, View v, int position, long id) { protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent; Intent intent;
String name; String name;
if (position == 29) { if (position == 29) {
intent = new Intent(this, ScreenManager.class); intent = new Intent(this, ScreenManager.class);
intent.setAction(Intent.ACTION_EDIT); intent.setAction(Intent.ACTION_EDIT);
@ -195,38 +227,9 @@ public class Shortcuts extends ResourceWrapperListActivity {
} else if (position >= 17 && position < 29) { } else if (position >= 17 && position < 29) {
intent.putExtra(Customize.INTENT_EXTRA_PAGE_ID, new ContainerPath(Page.APP_DRAWER_PAGE).toString()); 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) { private void createShortcutForIntent(String name, Intent intent) {
@ -239,7 +242,7 @@ public class Shortcuts extends ResourceWrapperListActivity {
Script script = LLApp.get().getAppEngine().getScriptManager().getOrLoadScript(id); Script script = LLApp.get().getAppEngine().getScriptManager().getOrLoadScript(id);
String extra_data = Script.encodeIdAndData(id, data); 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 // for scripts triggered by Tasker, pass the data as a string extra otherwise '%' is escaped in Intent.toUri
Intent result = new Intent(); Intent result = new Intent();
@ -252,16 +255,16 @@ public class Shortcuts extends ResourceWrapperListActivity {
} }
result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE, bundle); result.putExtra(com.twofortyfouram.locale.Intent.EXTRA_BUNDLE, bundle);
String data_e; String data_e;
if(data == null) { if (data == null) {
data_e = ""; data_e = "";
} else { } else {
if(data.length()>30) { if (data.length() > 30) {
data_e = data.substring(0, 30)+""; data_e = data.substring(0, 30) + "";
} else { } else {
data_e = data; 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); setResult(RESULT_OK, result);
} else { } else {
Intent intent = new Intent(Shortcuts.this, Dashboard.class); 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) { public void onScriptPicked(String id_data, int target) {
final Pair<Integer, String> pair = Script.decodeIdAndData(id_data); final Pair<Integer, String> pair = Script.decodeIdAndData(id_data);
createScriptShortcut(pair.first, pair.second, target); createScriptShortcut(pair.first, pair.second, target);
if(mIsForTaskerScript) { if (mIsForTaskerScript) {
finish(); finish();
} }
} }
@Override @Override
public void onScriptPickerCanceled() { public void onScriptPickerCanceled() {
if(mIsForTaskerScript) { if (mIsForTaskerScript) {
finish(); finish();
} }
} }
@ -307,7 +310,7 @@ public class Shortcuts extends ResourceWrapperListActivity {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putInt(LightningIntent.INTENT_EXTRA_ACTION, GlobalConfig.SET_VARIABLE); 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)) { if (TaskerPlugin.Setting.hostSupportsOnFireVariableReplacement(Shortcuts.this)) {
TaskerPlugin.Setting.setVariableReplaceKeys(bundle, new String[]{LightningIntent.INTENT_EXTRA_DATA}); TaskerPlugin.Setting.setVariableReplaceKeys(bundle, new String[]{LightningIntent.INTENT_EXTRA_DATA});
} }
@ -324,9 +327,4 @@ public class Shortcuts extends ResourceWrapperListActivity {
} }
}).show(); }).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[]{ 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.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_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_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), 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.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, 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_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), 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.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.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.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), 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.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.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_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.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.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.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), 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.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.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_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), 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.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.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.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), 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 final ArrayList<Action> mActions;
private String mActionNames[]; private final String[] mActionNames;
private int mType; private final int mType;
private boolean mForItem; private final boolean mForItem;
public ActionsDescription(Context context, int type, boolean forItem) { public ActionsDescription(Context context, int type, boolean forItem) {
mActions = new ArrayList<>(sAllActions.length); mActions = new ArrayList<>(sAllActions.length);
@ -113,7 +113,7 @@ public final class ActionsDescription {
mForItem = forItem; mForItem = forItem;
for (Action action : sAllActions) { for (Action action : sAllActions) {
boolean isItem = (action.flags & Action.FLAG_ITEM) == Action.FLAG_ITEM; 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); mActions.add(action);
} }
} }
@ -144,18 +144,18 @@ public final class ActionsDescription {
} }
} }
return 0; return 0;
} }
public String getActionName(int action) { public String getActionName(int action) {
return mActionNames[getActionIndex(action)]; return mActionNames[getActionIndex(action)];
} }
public int getActionAt(int index) { public int getActionAt(int index) {
return mActions.get(index).action; return mActions.get(index).action;
} }
public String[] getActionNames() { public String[] getActionNames() {
return mActionNames; 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.FolderConfig;
import net.pierrox.lightning_launcher.configuration.ItemConfig; import net.pierrox.lightning_launcher.configuration.ItemConfig;
import net.pierrox.lightning_launcher.engine.LightningEngine; import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.views.item.ItemView; import net.pierrox.lightning_launcher.views.item.ItemView;
import org.json.JSONException; import org.json.JSONException;
@ -40,10 +39,176 @@ import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
public class UndoStack { 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 interface UndoListener {
public void onUndoStackStateChanged(boolean can_undo, boolean can_redo); void onUndoStackStateChanged(boolean can_undo, boolean can_redo);
public void onUndoStackItemChanged(Item item);
public void onUndoStackPageChanged(Page page); void onUndoStackItemChanged(Item item);
void onUndoStackPageChanged(Page page);
} }
private abstract class Operation { private abstract class Operation {
@ -64,7 +229,7 @@ public class UndoStack {
protected File getTempStorageDirectory() { protected File getTempStorageDirectory() {
File dir = new File(mTempStorageDirectory, String.valueOf(hashCode())); File dir = new File(mTempStorageDirectory, String.valueOf(hashCode()));
if(!dir.exists()) { if (!dir.exists()) {
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
dir.mkdirs(); dir.mkdirs();
} }
@ -94,7 +259,7 @@ public class UndoStack {
private class GroupStartOperation extends Operation { private class GroupStartOperation extends Operation {
protected GroupStartOperation(SelectionState selectionState) { protected GroupStartOperation(SelectionState selectionState) {
if(selectionState != null) { if (selectionState != null) {
mSelectionState = selectionState; mSelectionState = selectionState;
} }
} }
@ -110,7 +275,7 @@ public class UndoStack {
do { do {
op = UndoStack.this.getNextRedoOperation(); op = UndoStack.this.getNextRedoOperation();
UndoStack.this.redo(); UndoStack.this.redo();
} while(op.getClass() != GroupEndOperation.class); } while (op.getClass() != GroupEndOperation.class);
super.redo(); super.redo();
} }
@ -129,10 +294,10 @@ public class UndoStack {
do { do {
op = UndoStack.this.getNextUndoOperation(); op = UndoStack.this.getNextUndoOperation();
// check for null because if the stack is full, older operations may have been removed, including balanced GroupStartOperation // 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(); UndoStack.this.undo();
} }
} while(op != null && op.getClass() != GroupStartOperation.class); } while (op != null && op.getClass() != GroupStartOperation.class);
} }
@Override @Override
@ -160,8 +325,8 @@ public class UndoStack {
} }
private class PageOperationItemZOrder extends PageOperation { private class PageOperationItemZOrder extends PageOperation {
private int mOldZOrder; private final int mOldZOrder;
private int mNewZOrder; private final int mNewZOrder;
protected PageOperationItemZOrder(Page page, Item item, int oldZOrder) { protected PageOperationItemZOrder(Page page, Item item, int oldZOrder) {
super(page); super(page);
@ -190,8 +355,8 @@ public class UndoStack {
} }
private class PageOperationAddOrRemoveItem extends PageOperation { private class PageOperationAddOrRemoveItem extends PageOperation {
private int mItemId; private final int mItemId;
private boolean mForAdd; private final boolean mForAdd;
private JSONObject mJsonItem; private JSONObject mJsonItem;
private int mZOrder; private int mZOrder;
@ -201,7 +366,7 @@ public class UndoStack {
mItemId = item.mId; mItemId = item.mId;
mForAdd = forAdd; mForAdd = forAdd;
if(!mForAdd) { if (!mForAdd) {
saveItemState(item); saveItemState(item);
} else { } else {
mZOrder = mPage.items.size(); mZOrder = mPage.items.size();
@ -211,7 +376,7 @@ public class UndoStack {
@Override @Override
protected void undo() { protected void undo() {
if(mForAdd) { if (mForAdd) {
doRemove(); doRemove();
notifyPageChanged(); notifyPageChanged();
} else { } else {
@ -223,7 +388,7 @@ public class UndoStack {
@Override @Override
protected void redo() { protected void redo() {
if(mForAdd) { if (mForAdd) {
doAdd(); doAdd();
mListener.onUndoStackPageChanged(mPage); mListener.onUndoStackPageChanged(mPage);
} else { } else {
@ -239,13 +404,15 @@ public class UndoStack {
private void saveItemState(Item item) { private void saveItemState(Item item) {
exchangeFilesWithUndo(item, true); exchangeFilesWithUndo(item, true);
try { mJsonItem = item.toJSONObject(); } catch (JSONException e) { /*pass*/ } try {
mJsonItem = item.toJSONObject();
} catch (JSONException e) { /*pass*/ }
mZOrder = mPage.items.indexOf(item); mZOrder = mPage.items.indexOf(item);
} }
private void doRemove() { private void doRemove() {
Item item = mPage.findItemById(mItemId); Item item = mPage.findItemById(mItemId);
if(mForAdd) { if (mForAdd) {
saveItemState(item); saveItemState(item);
} }
mPage.removeItem(item, false); 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) { private void exchangeFilesWithUndo(Item item, boolean direction) {
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
@ -276,9 +443,9 @@ public class UndoStack {
ArrayList<File> icons = new ArrayList<>(); ArrayList<File> icons = new ArrayList<>();
item.getIconFiles(mPage.getIconDir(), icons); item.getIconFiles(mPage.getIconDir(), icons);
int index = 0; int index = 0;
for(File from : icons) { for (File from : icons) {
File to = new File(out, String.valueOf(index)); File to = new File(out, String.valueOf(index));
if(direction) { if (direction) {
Utils.copyFileSafe(buffer, from, to); Utils.copyFileSafe(buffer, from, to);
} else { } else {
Utils.copyFileSafe(buffer, to, from); Utils.copyFileSafe(buffer, to, from);
@ -286,8 +453,8 @@ public class UndoStack {
index++; index++;
} }
if(item instanceof Folder) { if (item instanceof Folder) {
Folder f = (Folder)item; Folder f = (Folder) item;
Page page = f.getOrLoadFolderPage(); Page page = f.getOrLoadFolderPage();
exchangePageFilesWithUndo(page, direction, buffer, new ArrayList<Integer>()); 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) { private void exchangePageFilesWithUndo(Page page, boolean direction, byte[] buffer, ArrayList<Integer> done) {
try { try {
File folder_dir = page.getPageDir(); File folder_dir = page.getPageDir();
File temp_dir = new File(getTempStorageDirectory(), "page_"+page.id); File temp_dir = new File(getTempStorageDirectory(), "page_" + page.id);
if(direction) { if (direction) {
if(page.isModified()) page.save(); if (page.isModified()) page.save();
Utils.copyDirectory(buffer, folder_dir, temp_dir); Utils.copyDirectory(buffer, folder_dir, temp_dir);
} else { } else {
Utils.copyDirectory(buffer, temp_dir, folder_dir); Utils.copyDirectory(buffer, temp_dir, folder_dir);
@ -308,11 +475,11 @@ public class UndoStack {
e.printStackTrace(); e.printStackTrace();
} }
for(Item item : page.items) { for (Item item : page.items) {
if(item instanceof Folder) { if (item instanceof Folder) {
Folder f = (Folder)item; Folder f = (Folder) item;
int pageId = f.getFolderPageId(); int pageId = f.getFolderPageId();
if(!done.contains(pageId)) { if (!done.contains(pageId)) {
// prevent endless recursion when the folder is in itself // prevent endless recursion when the folder is in itself
done.add(pageId); done.add(pageId);
exchangePageFilesWithUndo(f.getOrLoadFolderPage(), direction, buffer, done); exchangePageFilesWithUndo(f.getOrLoadFolderPage(), direction, buffer, done);
@ -351,7 +518,7 @@ public class UndoStack {
exchangeFilesWithUndo(!direction, true); exchangeFilesWithUndo(!direction, true);
exchangeFilesWithUndo(direction, false); exchangeFilesWithUndo(direction, false);
mPage.reload(); mPage.reload();
if(previous_style != mPage.config.defaultFolderConfig.iconStyle) { if (previous_style != mPage.config.defaultFolderConfig.iconStyle) {
Utils.updateFolderIconStyle(mPage); Utils.updateFolderIconStyle(mPage);
} }
mListener.onUndoStackPageChanged(mPage); mListener.onUndoStackPageChanged(mPage);
@ -389,6 +556,7 @@ public class UndoStack {
private abstract class ItemOperation extends Operation { private abstract class ItemOperation extends Operation {
protected int itemId; protected int itemId;
public ItemOperation(Item item) { public ItemOperation(Item item) {
this.itemId = item.getId(); this.itemId = item.getId();
} }
@ -442,7 +610,8 @@ public class UndoStack {
} }
private class ItemOperationGridAttachment extends ItemOperationSetGeometry { private class ItemOperationGridAttachment extends ItemOperationSetGeometry {
private boolean wasAttached; private final boolean wasAttached;
private ItemOperationGridAttachment(ItemView itemView, boolean wasAttached, SavedItemGeometry oldGeometry) { private ItemOperationGridAttachment(ItemView itemView, boolean wasAttached, SavedItemGeometry oldGeometry) {
super(itemView, oldGeometry); super(itemView, oldGeometry);
this.wasAttached = wasAttached; this.wasAttached = wasAttached;
@ -466,8 +635,9 @@ public class UndoStack {
} }
private class ItemOperationPinMode extends ItemOperationSetGeometry { private class ItemOperationPinMode extends ItemOperationSetGeometry {
private ItemConfig.PinMode oldPinMode; private final ItemConfig.PinMode oldPinMode;
private ItemConfig.PinMode newPinMode; private final ItemConfig.PinMode newPinMode;
private ItemOperationPinMode(ItemView itemView, ItemConfig.PinMode oldPinMode, SavedItemGeometry oldGeometry) { private ItemOperationPinMode(ItemView itemView, ItemConfig.PinMode oldPinMode, SavedItemGeometry oldGeometry) {
super(itemView, oldGeometry); super(itemView, oldGeometry);
this.oldPinMode = oldPinMode; this.oldPinMode = oldPinMode;
@ -492,10 +662,10 @@ public class UndoStack {
} }
private class ItemOperationMove extends ItemOperationSetGeometry { private class ItemOperationMove extends ItemOperationSetGeometry {
private int mOldItemId; private final int mOldItemId;
private int mNewItemId; private final int mNewItemId;
private int mOldPage; private final int mOldPage;
private int mNewPage; private final int mNewPage;
private ItemOperationMove(ItemView itemView, int oldItemId, SavedItemGeometry oldGeometry) { private ItemOperationMove(ItemView itemView, int oldItemId, SavedItemGeometry oldGeometry) {
super(itemView, oldGeometry); super(itemView, oldGeometry);
@ -546,7 +716,9 @@ public class UndoStack {
public ItemOperationState(Item item) { public ItemOperationState(Item item) {
super(item); super(item);
try { mOldJsonItem = item.toJSONObject(); } catch (JSONException e) { /*pass*/ } try {
mOldJsonItem = item.toJSONObject();
} catch (JSONException e) { /*pass*/ }
ArrayList<File> icons = new ArrayList<>(); ArrayList<File> icons = new ArrayList<>();
Page page = item.getPage(); Page page = item.getPage();
@ -563,7 +735,9 @@ public class UndoStack {
exchangeFilesWithUndo(icons, false, true); // save new files to temp 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 { try {
int zorder = page.items.indexOf(new_item); int zorder = page.items.indexOf(new_item);
@ -610,17 +784,17 @@ public class UndoStack {
private void exchangeFilesWithUndo(ArrayList<File> icons, boolean old, boolean direction) { private void exchangeFilesWithUndo(ArrayList<File> icons, boolean old, boolean direction) {
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
File out = new File(getTempStorageDirectory(), old?"o":"n"); File out = new File(getTempStorageDirectory(), old ? "o" : "n");
out.mkdir(); out.mkdir();
int index = 0; int index = 0;
for(File from : icons) { for (File from : icons) {
File to = new File(out, String.valueOf(index)); File to = new File(out, String.valueOf(index));
if(!direction) { if (!direction) {
File tmp = to; File tmp = to;
to = from; to = from;
from = tmp; from = tmp;
} }
if(from.exists()) { if (from.exists()) {
Utils.copyFileSafe(buffer, from, to); Utils.copyFileSafe(buffer, from, to);
} else { } else {
to.delete(); 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). * 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 { public class LLPreference {
private int mId; private final int mId;
protected String mTitle; protected String mTitle;
protected String mSummary; protected String mSummary;
protected boolean mDisabled; protected boolean mDisabled;
protected boolean mIsLocked; protected boolean mIsLocked;
protected boolean mVisible = true; protected boolean mVisible = true;
protected Object mValue; protected Object mValue;
protected Object mDefaultValue; protected Object mDefaultValue;
/** /**
* @hide * @hide
*/ */
public LLPreference(Context context, int id, int title, int summary) { public LLPreference(Context context, int id, int title, int summary) {
this(context, id, title, summary, null, null); this(context, id, title, summary, null, null);
} }
/** /**
* @hide * @hide
*/ */
public LLPreference(Context context, int id, int title, int summary, Object value, Object defaultValue) { 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); this(id, title == 0 ? null : context.getString(title), summary == 0 ? null : context.getString(summary), value, defaultValue);
} }
/** /**
* Create a new preference. * Create a new preference.
* @param id a unique number to identify the preference, use 0 if unused. *
* @param title Displayed title. * @param id a unique number to identify the preference, use 0 if unused.
* @param summary Displayed summary, use null for none. * @param title Displayed title.
* @param value Value for the preference. * @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 defaultValue Default value if displaying the override checkbox. Use null if unused.
*/ */
public LLPreference(int id, String title, String summary, Object value, Object defaultValue) { public LLPreference(int id, String title, String summary, Object value, Object defaultValue) {
mId = id; mId = id;
mTitle = title; mTitle = title;
mSummary = summary; mSummary = summary;
setValue(value, defaultValue); setValue(value, defaultValue);
} }
/** /**
* Set the value and optionally a default value. * Set the value and optionally a default value.
* @param value the value stored by this preference *
* @param defaultValue use null if unused * @param value the value stored by this preference
* @param defaultValue use null if unused
*/ */
public void setValue(Object value, Object defaultValue) { public void setValue(Object value, Object defaultValue) {
mValue = value; mValue = value;
mDefaultValue = defaultValue; mDefaultValue = defaultValue;
} }
/** /**
* Return the unique identifier. * Return the unique identifier.
*/ */
public int getId() { public int getId() {
return mId; return mId;
} }
/** /**
* Return the title. * Return the title.
*/ */
public String getTitle() { public String getTitle() {
return mTitle; return mTitle;
} }
/** /**
* Set a new title. * Set a new title.
*/ */
public void setTitle(String title) { public void setTitle(String title) {
mTitle = title; mTitle = title;
} }
/** /**
* Return the summary, if any. * Return the summary, if any.
*/ */
public String getSummary() { public String getSummary() {
return mSummary; return mSummary;
} }
/** /**
* Set a new summary. * Set a new summary.
*/ */
public void setSummary(String summary) { public void setSummary(String summary) {
mSummary = 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) { public boolean isDisabled() {
mDisabled = disabled; return mDisabled;
}
/**
* 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;
} }
/** /**
* @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() { public boolean isLocked() {
return mIsLocked; return mIsLocked;
} }
/** /**
* Show or hide this preference. * @hide
*/ */
public void setVisible(boolean visible) { public void setLocked(boolean locked) {
mVisible = visible; mIsLocked = locked;
} }
/** /**
* Return true is the preference is currently visible. * Return true is the preference is currently visible.
*/ */
public boolean isVisible() { public boolean isVisible() {
return mVisible; return mVisible;
} }
/** /**
* Set the value of this preference with the default value. * Show or hide this preference.
*/ */
public void reset() { public void setVisible(boolean visible) {
mValue = mDefaultValue; 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. * 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 { public class LLPreferenceColor extends LLPreference {
private boolean mHasAlpha; private final boolean mHasAlpha;
/** /**
* Create a new color preference * Create a new color preference
* @param id a unique number to identify the preference, use 0 if unused. *
* @param title Displayed title. * @param id a unique number to identify the preference, use 0 if unused.
* @param summary Displayed summary, use null for none. * @param title Displayed title.
* @param color Color for the preference as a 32 bits ARGB value. * @param summary Displayed summary, use null for none.
* @param default_color Default color if displaying the override checkbox. Use null if unused. * @param color Color for the preference as a 32 bits ARGB value.
* @param has_alpha true to allow transparency setting * @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) { public LLPreferenceColor(int id, String title, String summary, int color, Integer default_color, boolean has_alpha) {
super(id, title, summary, color, default_color); super(id, title, summary, color, default_color);
mHasAlpha = has_alpha; mHasAlpha = has_alpha;
} }
/** /**
* @hide * @hide
*/ */
public LLPreferenceColor(Context context, int id, int title, int summary, boolean has_alpha) { public LLPreferenceColor(Context context, int id, int title, int summary, boolean has_alpha) {
super(context, id, title, summary); super(context, id, title, summary);
mHasAlpha = has_alpha; mHasAlpha = has_alpha;
} }
/** /**
* @hide * @hide
*/ */
public LLPreferenceColor(Context context, int id, int title, int summary, int color, Integer default_color, boolean has_alpha) { 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); super(context, id, title, summary, Integer.valueOf(color), default_color);
mHasAlpha = has_alpha; mHasAlpha = has_alpha;
} }
/** /**
* Return the currently selected color. * Return the currently selected color.
*/ */
public int getColor() { public int getColor() {
return (Integer)mValue; return (Integer) mValue;
} }
/** /**
* Set this preference color. * Set this preference color.
* @param color a 32 bits ARGB value *
* @param color a 32 bits ARGB value
*/ */
public void setColor(int color) { public void setColor(int color) {
mValue = Integer.valueOf(color); mValue = Integer.valueOf(color);
} }
/** /**
* Set this preference default color. * Set this preference default color.
* @param color a 32 bits ARGB value *
*/ * @param color a 32 bits ARGB value
public void setDefaultColor(int color) {
mDefaultValue = Integer.valueOf(color);
}
/**
* Return true is this preference allows alpha configuration
*/ */
public boolean hasAlpha() { public void setDefaultColor(int color) {
return mHasAlpha; 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 { 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) { 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); super(id, context.getString(title), actions.getActionName(value.action), value, defaultValue);
@ -51,14 +51,14 @@ public class LLPreferenceEventAction extends LLPreference {
return (EventAction) mValue; return (EventAction) mValue;
} }
@Override public void setValue(EventAction ea) {
public void setValue(Object value, Object defaultValue) { mValue = ea;
super.setValue(value, defaultValue);
updateLabel(); updateLabel();
} }
public void setValue(EventAction ea) { @Override
mValue = ea; public void setValue(Object value, Object defaultValue) {
super.setValue(value, defaultValue);
updateLabel(); updateLabel();
} }
@ -68,7 +68,7 @@ public class LLPreferenceEventAction extends LLPreference {
private void updateLabel() { private void updateLabel() {
EventAction ea = getValue(); EventAction ea = getValue();
if(ea == null || mActions == null) { if (ea == null || mActions == null) {
setSummary(""); setSummary("");
} else { } else {
String more = ea.next == null ? "" : " (+)"; 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.margaritov.preference.colorpicker.ColorPickerPanelView;
import net.pierrox.lightning_launcher.LLApp; import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.LLAppPhone; 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.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;
import net.pierrox.lightning_launcher.views.BoxEditorView.OnBoxEditorEventListener; import net.pierrox.lightning_launcher.views.BoxEditorView.OnBoxEditorEventListener;
import net.pierrox.lightning_launcher_extreme.R; 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 class LLPreferenceListView extends ListView implements OnItemClickListener, OnColorChangedListener, DialogInterface.OnClickListener, AdapterView.OnItemLongClickListener, DialogPreferenceSlider.OnDialogPreferenceSliderListener {
public interface OnLLPreferenceListViewEventListener { private LLPreferenceColor mDialogColorPreference;
public void onLLPreferenceClicked(LLPreference preference); private LLPreferenceSlider mDialogSliderPreference;
public void onLLPreferenceLongClicked(LLPreference preference); private LLPreferenceList mDialogListPreference;
public void onLLPreferenceChanged(LLPreference preference); private LLPreferenceText mDialogTextPreference;
/** @hide */ public void onLLPreferenceBindingRemoved(LLPreferenceBinding preference); 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 mCompactMode;
private boolean mDisplayOverride; private boolean mDisplayOverride;
private OnLLPreferenceListViewEventListener mOnLLPreferenceListViewEventListener;
private OnLLPreferenceListViewEventListener mOnLLPreferenceListViewEventListener; /**
* Default constructor.
/**
* Default constructor.
*/
public LLPreferenceListView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnItemClickListener(this);
setOnItemLongClickListener(this);
}
/**
* @hide
*/ */
@Override public LLPreferenceListView(Context context, AttributeSet attrs) {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { super(context, attrs);
Context context = getContext();
LLPreference p = (LLPreference)parent.getItemAtPosition(position); setOnItemClickListener(this);
if(p.isLocked()) { 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); LLApp.get().showFeatureLockedDialog(context);
return; return;
} }
if(p.isDisabled()) { if (p.isDisabled()) {
return; return;
} }
if(mDialog != null) { if (mDialog != null) {
mDialog.dismiss(); mDialog.dismiss();
} }
mDialog = null; mDialog = null;
if(p instanceof LLPreferenceCheckBox) { if (p instanceof LLPreferenceCheckBox) {
LLPreferenceCheckBox cbp = (LLPreferenceCheckBox)p; LLPreferenceCheckBox cbp = (LLPreferenceCheckBox) p;
cbp.setChecked(!cbp.isChecked()); cbp.setChecked(!cbp.isChecked());
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(cbp); if (mOnLLPreferenceListViewEventListener != null)
} else if(p instanceof LLPreferenceColor) { mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(cbp);
mDialogColorPreference = (LLPreferenceColor)p; } else if (p instanceof LLPreferenceColor) {
ColorPickerDialog color_picker_dialog = new ColorPickerDialog(context, mDialogColorPreference.getColor()); mDialogColorPreference = (LLPreferenceColor) p;
color_picker_dialog.setAlphaSliderVisible(mDialogColorPreference.hasAlpha()); ColorPickerDialog color_picker_dialog = new ColorPickerDialog(context, mDialogColorPreference.getColor());
color_picker_dialog.setOnColorChangedListener(this); color_picker_dialog.setAlphaSliderVisible(mDialogColorPreference.hasAlpha());
mDialog = color_picker_dialog; color_picker_dialog.setOnColorChangedListener(this);
} else if(p instanceof LLPreferenceSlider) { mDialog = color_picker_dialog;
mDialogSliderPreference = (LLPreferenceSlider)p; } else if (p instanceof LLPreferenceSlider) {
LLPreferenceSlider sp = mDialogSliderPreference; mDialogSliderPreference = (LLPreferenceSlider) p;
DialogPreferenceSlider slider_dialog = new DialogPreferenceSlider(context, sp.getValue(), sp.getValueType()== LLPreferenceSlider.ValueType.FLOAT, sp.getMinValue(), sp.getMaxValue(), sp.getInterval(), sp.getUnit(), this); LLPreferenceSlider sp = mDialogSliderPreference;
slider_dialog.setTitle(sp.getTitle()); DialogPreferenceSlider slider_dialog = new DialogPreferenceSlider(context, sp.getValue(), sp.getValueType() == LLPreferenceSlider.ValueType.FLOAT, sp.getMinValue(), sp.getMaxValue(), sp.getInterval(), sp.getUnit(), this);
mDialog = slider_dialog; slider_dialog.setTitle(sp.getTitle());
} else if(p instanceof LLPreferenceText) { mDialog = slider_dialog;
mDialogTextPreference = (LLPreferenceText)p; } else if (p instanceof LLPreferenceText) {
mDialogTextPreference = (LLPreferenceText) p;
LLPreferenceText tp = mDialogTextPreference; LLPreferenceText tp = mDialogTextPreference;
LLPreferenceTextDialog text_dialog = new LLPreferenceTextDialog(context, tp.getValue()); LLPreferenceTextDialog text_dialog = new LLPreferenceTextDialog(context, tp.getValue());
text_dialog.setTitle(tp.getTitle()); text_dialog.setTitle(tp.getTitle());
mDialog = text_dialog; mDialog = text_dialog;
} else if(p instanceof LLPreferenceList) { } else if (p instanceof LLPreferenceList) {
mDialogListPreference = (LLPreferenceList)p; mDialogListPreference = (LLPreferenceList) p;
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(mDialogListPreference.getTitle()); builder.setTitle(mDialogListPreference.getTitle());
builder.setSingleChoiceItems(mDialogListPreference.getLabels(), mDialogListPreference.getValueIndex(), this); builder.setSingleChoiceItems(mDialogListPreference.getLabels(), mDialogListPreference.getValueIndex(), this);
builder.setNegativeButton(android.R.string.cancel, null); builder.setNegativeButton(android.R.string.cancel, null);
mDialog = builder.create(); mDialog = builder.create();
} }
if(mDialog != null) { if (mDialog != null) {
mDialogPreference = p; mDialogPreference = p;
mDialog.show(); mDialog.show();
} }
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceClicked(p);
}
/** if (mOnLLPreferenceListViewEventListener != null)
* @hide mOnLLPreferenceListViewEventListener.onLLPreferenceClicked(p);
*/ }
@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 @Override
public void onColorChanged(int color) { public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
mDialogColorPreference.setColor(color); LLPreference p = (LLPreference) parent.getItemAtPosition(position);
mAdapter.notifyDataSetChanged(); if (mOnLLPreferenceListViewEventListener != null)
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogColorPreference); 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 @Override
public void onColorDialogSelected(int color) { public void onColorDialogSelected(int color) {
// pass // pass
} }
/** /**
* @hide * @hide
*/ */
@Override @Override
public void onColorDialogCanceled() { public void onColorDialogCanceled() {
// pass // pass
} }
/** /**
* @hide * @hide
*/ */
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
mDialogListPreference.setValueIndex(which); mDialogListPreference.setValueIndex(which);
dialog.dismiss(); dialog.dismiss();
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogListPreference); 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) { public void setListener(OnLLPreferenceListViewEventListener listener) {
mOnLLPreferenceListViewEventListener = 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() { public ArrayList<LLPreference> getPreferences() {
return mAdapter == null ? null : mAdapter.getObjects(); return mAdapter == null ? null : mAdapter.getObjects();
} }
/** /**
* Request a manual refresh. * Set the list of preferences to display in this listview.
*/ */
public void refresh() { public void setPreferences(LLPreference[] preferences) {
int count = mAdapter.getCount(); setPreferences(new ArrayList<>(Arrays.asList(preferences)));
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 * @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 @Override
public void onDialogPreferenceSliderValueSet(float value) { public void onDialogPreferenceSliderValueSet(float value) {
mDialogSliderPreference.setValue(value); mDialogSliderPreference.setValue(value);
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogSliderPreference); if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogSliderPreference);
} }
/** /**
* @hide * @hide
*/ */
@Override @Override
public void onDialogPreferenceSliderCancel() { public void onDialogPreferenceSliderCancel() {
// pass // pass
} }
/** /**
* Use a mode where preferences are displayed using a more compact layout * 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. *
* @param compactMode true to shrink preferences and display more preferences in a screen.
*/ */
public void setCompactMode(boolean compactMode) { public void setCompactMode(boolean compactMode) {
mCompactMode = 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) { public void setDisplayOverride(boolean displayOverride) {
mDisplayOverride = displayOverride; mDisplayOverride = displayOverride;
if(mAdapter != null) { if (mAdapter != null) {
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
} }
} }
private class PrefAdapter extends ArrayAdapter<LLPreference> implements OnCheckedChangeListener, OnBoxEditorEventListener, OnClickListener { public interface OnLLPreferenceListViewEventListener {
private int mPrefLayout; void onLLPreferenceClicked(LLPreference preference);
private int mPrefCategoryLayout;
private int mPrefListWidgetLayout; void onLLPreferenceLongClicked(LLPreference preference);
private float mPrefSizeCategory;
private float mPrefSizeTitle; void onLLPreferenceChanged(LLPreference preference);
private float mPrefSizeSummary;
private LayoutInflater mLayoutInflater; /**
private float mDensity; * @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> mObjects;
ArrayList<LLPreference> mFilteredObjects; ArrayList<LLPreference> mFilteredObjects;
public PrefAdapter(Context context, int textViewResourceId, ArrayList<LLPreference> objects) { public PrefAdapter(Context context, int textViewResourceId, ArrayList<LLPreference> objects) {
super(context, textViewResourceId); super(context, textViewResourceId);
mPrefLayout = new Preference(context).getLayoutResource(); mPrefLayout = new Preference(context).getLayoutResource();
mPrefCategoryLayout = new PreferenceCategory(context).getLayoutResource(); mPrefCategoryLayout = new PreferenceCategory(context).getLayoutResource();
mPrefListWidgetLayout = new ListPreference(context).getWidgetLayoutResource(); mPrefListWidgetLayout = new ListPreference(context).getWidgetLayoutResource();
mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resources resources = getResources(); Resources resources = getResources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics(); DisplayMetrics displayMetrics = resources.getDisplayMetrics();
mDensity = displayMetrics.density; mDensity = displayMetrics.density;
@ -312,24 +320,24 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
mPrefSizeSummary = resources.getDimensionPixelSize(R.dimen.pref_size_summary) / scaledDensity; mPrefSizeSummary = resources.getDimensionPixelSize(R.dimen.pref_size_summary) / scaledDensity;
mObjects = objects; mObjects = objects;
filterObjects(); filterObjects();
} }
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
LLPreference p = getItem(position); LLPreference p = getItem(position);
boolean is_category = p instanceof LLPreferenceCategory; boolean is_category = p instanceof LLPreferenceCategory;
if(p instanceof LLPreferenceBox) { if (p instanceof LLPreferenceBox) {
if(convertView == null) { if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.box_config, null); convertView = mLayoutInflater.inflate(R.layout.box_config, null);
((TextView)convertView.findViewById(R.id.box_h)).setText(R.string.b_hint); ((TextView) convertView.findViewById(R.id.box_h)).setText(R.string.b_hint);
((BoxEditorView)convertView.findViewById(R.id.box)).setOnBoxEditorEventListener(p, this); ((BoxEditorView) convertView.findViewById(R.id.box)).setOnBoxEditorEventListener(p, this);
} }
} else { } else {
if(convertView == null) { if (convertView == null) {
View preference_view = mLayoutInflater.inflate(is_category ? mPrefCategoryLayout : mPrefLayout, null); View preference_view = mLayoutInflater.inflate(is_category ? mPrefCategoryLayout : mPrefLayout, null);
if(mCompactMode) { if (mCompactMode) {
TextView title_view = (TextView) preference_view.findViewById(android.R.id.title); TextView title_view = preference_view.findViewById(android.R.id.title);
if (is_category) { if (is_category) {
title_view.setTextSize(mPrefSizeCategory); title_view.setTextSize(mPrefSizeCategory);
} else { } else {
@ -339,68 +347,68 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
preference_view.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.pref_height)); preference_view.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.pref_height));
} }
} }
preference_view = ((LLAppPhone)LLApp.get()).managePreferenceViewLockedFlag(p, preference_view); preference_view = ((LLAppPhone) LLApp.get()).managePreferenceViewLockedFlag(p, preference_view);
View icon = preference_view.findViewById(android.R.id.icon); View icon = preference_view.findViewById(android.R.id.icon);
if(icon != null) { if (icon != null) {
((View)icon.getParent()).setVisibility(View.GONE); ((View) icon.getParent()).setVisibility(View.GONE);
} }
ViewGroup widget_frame = (ViewGroup) preference_view.findViewById(android.R.id.widget_frame); ViewGroup widget_frame = preference_view.findViewById(android.R.id.widget_frame);
if(is_category) { if (is_category) {
//preference_view.setEnabled(false); //preference_view.setEnabled(false);
} else if(p instanceof LLPreferenceList) { } else if (p instanceof LLPreferenceList) {
if(mPrefListWidgetLayout != 0) { if (mPrefListWidgetLayout != 0) {
mLayoutInflater.inflate(mPrefListWidgetLayout, widget_frame); mLayoutInflater.inflate(mPrefListWidgetLayout, widget_frame);
} }
} else if(p instanceof LLPreferenceCheckBox) { } else if (p instanceof LLPreferenceCheckBox) {
CheckBox widget = new CheckBox(getContext()); CheckBox widget = new CheckBox(getContext());
widget.setFocusable(false); widget.setFocusable(false);
widget.setClickable(false); widget.setClickable(false);
widget_frame.addView(widget); widget_frame.addView(widget);
} else if(p instanceof LLPreferenceColor) { } else if (p instanceof LLPreferenceColor) {
View v = new ColorPickerPanelView(getContext()); View v = new ColorPickerPanelView(getContext());
int s = (int)(30*mDensity); int s = (int) (30 * mDensity);
v.setLayoutParams(new FrameLayout.LayoutParams(s, s)); v.setLayoutParams(new FrameLayout.LayoutParams(s, s));
widget_frame.addView(v); widget_frame.addView(v);
} else if(p instanceof LLPreferenceSlider) { } else if (p instanceof LLPreferenceSlider) {
mLayoutInflater.inflate(R.layout.llpref_slider, widget_frame); mLayoutInflater.inflate(R.layout.llpref_slider, widget_frame);
} else if(p instanceof LLPreferenceBinding) { } else if (p instanceof LLPreferenceBinding) {
Button widget = new Button(getContext()); Button widget = new Button(getContext());
widget.setText("4"); widget.setText("4");
widget.setTypeface(LLApp.get().getIconsTypeface()); widget.setTypeface(LLApp.get().getIconsTypeface());
widget.setOnClickListener(this); widget.setOnClickListener(this);
widget.setFocusable(false); widget.setFocusable(false);
widget_frame.addView(widget); widget_frame.addView(widget);
} }
convertView = mLayoutInflater.inflate(R.layout.override_preference, null, false); convertView = mLayoutInflater.inflate(R.layout.override_preference, null, false);
CheckBox override = (CheckBox)convertView.findViewById(R.id.override); CheckBox override = convertView.findViewById(R.id.override);
override.setOnCheckedChangeListener(this); override.setOnCheckedChangeListener(this);
LinearLayout container = (LinearLayout)convertView.findViewById(R.id.content); LinearLayout container = convertView.findViewById(R.id.content);
container.addView(preference_view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_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); View override_g = convertView.findViewById(R.id.override_g);
TextView override_t = (TextView) override_g.findViewById(R.id.override_t); TextView override_t = override_g.findViewById(R.id.override_t);
CheckBox override = (CheckBox)convertView.findViewById(R.id.override); CheckBox override = convertView.findViewById(R.id.override);
override.setTag(p); override.setTag(p);
if(!is_category && p.isShowingOverride() && mDisplayOverride) { if (!is_category && p.isShowingOverride() && mDisplayOverride) {
boolean overriding = p.isOverriding(); boolean overriding = p.isOverriding();
boolean enabled = overriding && !p.isDisabled(); boolean enabled = overriding && !p.isDisabled();
override.setChecked(overriding); override.setChecked(overriding);
override.setEnabled(enabled); override.setEnabled(enabled);
override_t.setEnabled(enabled); override_t.setEnabled(enabled);
override_t.setText(R.string.ovr_custom); override_t.setText(R.string.ovr_custom);
override_g.setVisibility(View.VISIBLE); override_g.setVisibility(View.VISIBLE);
} else { } else {
override_g.setVisibility(is_category || !mDisplayOverride ? View.GONE : View.INVISIBLE); override_g.setVisibility(is_category || !mDisplayOverride ? View.GONE : View.INVISIBLE);
} }
String title; String title;
if(p instanceof LLPreferenceBinding) { if (p instanceof LLPreferenceBinding) {
Binding b = ((LLPreferenceBinding)p).getValue(); Binding b = ((LLPreferenceBinding) p).getValue();
Property prop = Property.getByName(b.target); Property prop = Property.getByName(b.target);
title = prop == null ? p.getTitle() : prop.getLabel(); title = prop == null ? p.getTitle() : prop.getLabel();
override.setChecked(b.enabled); override.setChecked(b.enabled);
@ -412,65 +420,65 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
title = p.getTitle(); title = p.getTitle();
} }
((TextView) convertView.findViewById(android.R.id.title)).setText(title); ((TextView) convertView.findViewById(android.R.id.title)).setText(title);
if(!is_category) { if (!is_category) {
String s = p.getSummary(); String s = p.getSummary();
TextView vs = (TextView) convertView.findViewById(android.R.id.summary); TextView vs = convertView.findViewById(android.R.id.summary);
if(s == null) { if (s == null) {
vs.setVisibility(View.GONE); vs.setVisibility(View.GONE);
} else { } else {
vs.setVisibility(View.VISIBLE); vs.setVisibility(View.VISIBLE);
vs.setText(s); vs.setText(s);
} }
} }
ViewGroup widget_frame = (ViewGroup) convertView.findViewById(android.R.id.widget_frame); ViewGroup widget_frame = convertView.findViewById(android.R.id.widget_frame);
if(is_category) { if (is_category) {
} else if(p instanceof LLPreferenceCheckBox) { } else if (p instanceof LLPreferenceCheckBox) {
CheckBox widget = (CheckBox) widget_frame.getChildAt(0); CheckBox widget = (CheckBox) widget_frame.getChildAt(0);
widget.setChecked(((LLPreferenceCheckBox)p).isChecked()); widget.setChecked(((LLPreferenceCheckBox) p).isChecked());
} else if(p instanceof LLPreferenceColor) { } else if (p instanceof LLPreferenceColor) {
// View color_preview = widget_frame.findViewById(R.id.color_preview); // View color_preview = widget_frame.findViewById(R.id.color_preview);
// color_preview.setBackgroundColor(((LLPreferenceColor)p).getColor()); // color_preview.setBackgroundColor(((LLPreferenceColor)p).getColor());
ColorPickerPanelView v = (ColorPickerPanelView)widget_frame.getChildAt(0); ColorPickerPanelView v = (ColorPickerPanelView) widget_frame.getChildAt(0);
v.setColor(((LLPreferenceColor)p).getColor()); v.setColor(((LLPreferenceColor) p).getColor());
} else if(p instanceof LLPreferenceSlider) { } else if (p instanceof LLPreferenceSlider) {
TextView tv_value = (TextView) widget_frame.findViewById(R.id.slider_value); TextView tv_value = widget_frame.findViewById(R.id.slider_value);
TextView tv_unit = (TextView) widget_frame.findViewById(R.id.slider_unit); TextView tv_unit = widget_frame.findViewById(R.id.slider_unit);
LLPreferenceSlider sp = (LLPreferenceSlider) p; LLPreferenceSlider sp = (LLPreferenceSlider) p;
String unit = sp.getUnit(); 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()); tv_unit.setText(sp.getUnit());
} else if(p instanceof LLPreferenceBinding) { } else if (p instanceof LLPreferenceBinding) {
widget_frame.getChildAt(0).setTag(p); 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()); if (!is_category) {
// should use dimensions from some resource
return convertView; convertView.setPadding(15, 0, 10, 0);
} }
private void setEnabledStateOnViews(View v, boolean enabled) {
v.setEnabled(enabled);
if (v instanceof ViewGroup) { setEnabledStateOnViews(convertView, !p.isDisabled());
final ViewGroup vg = (ViewGroup) v;
for (int i = vg.getChildCount() - 1; i >= 0; i--) { return convertView;
View c = vg.getChildAt(i); }
// do not change the override checkbox
int id=c.getId(); private void setEnabledStateOnViews(View v, boolean enabled) {
if(id!=R.id.override && id!=R.id.override_t) { v.setEnabled(enabled);
setEnabledStateOnViews(c, 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 @Override
public void notifyDataSetChanged() { public void notifyDataSetChanged() {
@ -489,73 +497,76 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
} }
@Override @Override
public boolean isEnabled(int position) { public boolean isEnabled(int position) {
return !(getItem(position) instanceof LLPreferenceCategory); return !(getItem(position) instanceof LLPreferenceCategory);
} }
@Override @Override
public boolean areAllItemsEnabled() { public boolean areAllItemsEnabled() {
return false; return false;
} }
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
LLPreference p = getItem(position); LLPreference p = getItem(position);
if(p instanceof LLPreferenceCategory) { if (p instanceof LLPreferenceCategory) {
return 1; return 1;
} else if(p instanceof LLPreferenceCheckBox) { } else if (p instanceof LLPreferenceCheckBox) {
return 2; return 2;
} else if(p instanceof LLPreferenceColor) { } else if (p instanceof LLPreferenceColor) {
return 3; return 3;
} else if(p instanceof LLPreferenceList) { } else if (p instanceof LLPreferenceList) {
return 4; return 4;
} else if(p instanceof LLPreferenceSlider) { } else if (p instanceof LLPreferenceSlider) {
return 5; return 5;
} else if(p instanceof LLPreferenceBox) { } else if (p instanceof LLPreferenceBox) {
return 6; return 6;
} else if(p instanceof LLPreferenceBinding) { } else if (p instanceof LLPreferenceBinding) {
return 7; return 7;
} }
return 0; return 0;
} }
@Override @Override
public int getViewTypeCount() { public int getViewTypeCount() {
// base pref, category, checkbox, color, slider, list, box, binding // base pref, category, checkbox, color, slider, list, box, binding
return 8; return 8;
} }
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
LLPreference p = (LLPreference)buttonView.getTag(); LLPreference p = (LLPreference) buttonView.getTag();
if(p instanceof LLPreferenceBinding) { if (p instanceof LLPreferenceBinding) {
Binding binding = ((LLPreferenceBinding) p).getValue(); Binding binding = ((LLPreferenceBinding) p).getValue();
if(binding.enabled != isChecked) { if (binding.enabled != isChecked) {
binding.enabled = isChecked; binding.enabled = isChecked;
if (mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p); if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
} }
} else { } else {
if (!isChecked) { if (!isChecked) {
if (p.isOverriding()) { if (p.isOverriding()) {
p.reset(); p.reset();
notifyDataSetChanged(); notifyDataSetChanged();
if (mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p); if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
} }
} }
} }
} }
@Override @Override
public void onBoxSelectionChanged(Object token, int selection) { public void onBoxSelectionChanged(Object token, int selection) {
LLPreferenceBox p = (LLPreferenceBox)token; LLPreferenceBox p = (LLPreferenceBox) token;
p.setSelection(selection); p.setSelection(selection);
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p); if (mOnLLPreferenceListViewEventListener != null)
} mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(p);
}
private void filterObjects() { private void filterObjects() {
mFilteredObjects = new ArrayList<>(); mFilteredObjects = new ArrayList<>();
for(LLPreference p : mObjects) { for (LLPreference p : mObjects) {
if(p.isVisible()) { if (p.isVisible()) {
mFilteredObjects.add(p); mFilteredObjects.add(p);
} }
} }
@ -564,7 +575,8 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
@Override @Override
public void onClick(View v) { public void onClick(View v) {
LLPreferenceBinding p = (LLPreferenceBinding) v.getTag(); LLPreferenceBinding p = (LLPreferenceBinding) v.getTag();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceBindingRemoved(p); if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceBindingRemoved(p);
} }
public ArrayList<LLPreference> getObjects() { public ArrayList<LLPreference> getObjects() {
@ -573,7 +585,7 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
} }
private class LLPreferenceTextDialog extends AlertDialog implements DialogInterface.OnClickListener { private class LLPreferenceTextDialog extends AlertDialog implements DialogInterface.OnClickListener {
private String mValue; private final String mValue;
private EditText mDialogEditText; private EditText mDialogEditText;
public LLPreferenceTextDialog(Context context, String value) { public LLPreferenceTextDialog(Context context, String value) {
@ -602,11 +614,12 @@ public class LLPreferenceListView extends ListView implements OnItemClickListene
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
switch(which) { switch (which) {
case BUTTON_POSITIVE: case BUTTON_POSITIVE:
mDialogTextPreference.setValue(mDialogEditText.getText().toString()); mDialogTextPreference.setValue(mDialogEditText.getText().toString());
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
if(mOnLLPreferenceListViewEventListener != null) mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogTextPreference); if (mOnLLPreferenceListViewEventListener != null)
mOnLLPreferenceListViewEventListener.onLLPreferenceChanged(mDialogTextPreference);
break; break;
} }
} }

View file

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

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_BOOKMARK = 16;
public static final int AI_LIGHTNING_ACTION = 17; public static final int AI_LIGHTNING_ACTION = 17;
public static final int AI_CUSTOM_VIEW = 18; public static final int AI_CUSTOM_VIEW = 18;
private final AddItemDialogInterface mAddItemDialogInterface;
public interface AddItemDialogInterface { private final LayoutInflater mInflater;
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;
public AddItemDialog(final Context context, boolean showPlugins, final AddItemDialogInterface addItemDialogInterface) { public AddItemDialog(final Context context, boolean showPlugins, final AddItemDialogInterface addItemDialogInterface) {
super(context); super(context);
mAddItemDialogInterface = addItemDialogInterface; 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); mInflater = LayoutInflater.from(context);
final ViewGroup content = (ViewGroup) mInflater.inflate(R.layout.add_dialog, null); final ViewGroup content = (ViewGroup) mInflater.inflate(R.layout.add_dialog, null);
final MyViewPager pager = (MyViewPager) content.findViewById(R.id.pager); final MyViewPager pager = content.findViewById(R.id.pager);
ViewGroup builtinsView = (ViewGroup) content.findViewById(R.id.builtins); ViewGroup builtinsView = content.findViewById(R.id.builtins);
final ListView pluginsListView = (ListView) content.findViewById(R.id.plugins); final ListView pluginsListView = content.findViewById(R.id.plugins);
final TabHost tabHost = (TabHost) content.findViewById(R.id.tab); final TabHost tabHost = content.findViewById(R.id.tab);
tabHost.setup(); tabHost.setup();
tabHost.addTab(tabHost.newTabSpec("B").setIndicator(context.getString(R.string.ad_b)).setContent(R.id.empty)); 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)); 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() { pager.setOnPageChangeListener(new MyViewPager.OnPageChangeListener() {
@Override @Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override @Override
public void onPageSelected(int position) { public void onPageSelected(int position) {
@ -129,7 +110,8 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
} }
@Override @Override
public void onPageScrollStateChanged(int state) { } public void onPageScrollStateChanged(int state) {
}
}); });
pluginsListView.setOnItemClickListener(this); pluginsListView.setOnItemClickListener(this);
@ -137,7 +119,7 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
setView(content); setView(content);
if(!showPlugins) { if (!showPlugins) {
tabHost.setVisibility(View.GONE); tabHost.setVisibility(View.GONE);
pager.removeViewAt(1); pager.removeViewAt(1);
} else { } else {
@ -225,18 +207,18 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
private ViewGroup addDialogAddCategory(ViewGroup root, int title) { private ViewGroup addDialogAddCategory(ViewGroup root, int title) {
View cat = mInflater.inflate(R.layout.add_dialog_cat, root, false); 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); 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) { private void addDialogAddItem(ViewGroup root, String label, String icon, int id) {
View item = mInflater.inflate(R.layout.add_dialog_item, root, false); 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); i.setText(icon);
LLAppPhone app = (LLAppPhone) LLApp.get(); LLAppPhone app = (LLAppPhone) LLApp.get();
i.setTypeface(app.getIconsTypeface()); i.setTypeface(app.getIconsTypeface());
((TextView)item.findViewById(R.id.label)).setText(label); ((TextView) item.findViewById(R.id.label)).setText(label);
item.setOnClickListener(this); item.setOnClickListener(this);
item.setTag(id); item.setTag(id);
Utils.setEnabledStateOnViews(item, mAddItemDialogInterface.isDialogAddItemEnabled(id)); Utils.setEnabledStateOnViews(item, mAddItemDialogInterface.isDialogAddItemEnabled(id));
@ -245,8 +227,30 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
root.addView(item); 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 static class PluginAdapter extends ArrayAdapter<Plugin> {
private LayoutInflater mLayoutInflater; private final LayoutInflater mLayoutInflater;
public PluginAdapter(Context context, List<Plugin> objects) { public PluginAdapter(Context context, List<Plugin> objects) {
super(context, 0, objects); super(context, 0, objects);
@ -261,7 +265,7 @@ public class AddItemDialog extends AlertDialog implements View.OnClickListener,
Plugin plugin = getItem(position); 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); line1.setText(plugin.label);
convertView.findViewById(android.R.id.text2).setVisibility(View.GONE); convertView.findViewById(android.R.id.text2).setVisibility(View.GONE);
((ImageView) convertView.findViewById(android.R.id.icon)).setImageDrawable(plugin.icon); ((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.SimpleExpandableListAdapter;
import android.widget.TextView; 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.LLApp;
import net.pierrox.lightning_launcher.data.Item; import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.engine.LightningEngine; 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.SharedAsyncGraphicsDrawable;
import net.pierrox.lightning_launcher.views.item.ItemView; import net.pierrox.lightning_launcher.views.item.ItemView;
import net.pierrox.lightning_launcher.views.item.ShortcutView; 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 net.pierrox.lightning_launcher_extreme.R;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
@ -65,19 +64,17 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class BindingEditDialog extends AlertDialog implements DialogInterface.OnClickListener, View.OnClickListener { public class BindingEditDialog extends AlertDialog implements DialogInterface.OnClickListener, View.OnClickListener {
public interface OnBindingEditDialogListener { private static final String ROOT_KEY = "r";
public void onBindingEdited(Binding binding, boolean open_in_script_editor); private static final String CHILD_KEY = "c";
} private final Binding mInitValue;
private final Binding[] mOtherBindings;
private Binding mInitValue; private final OnBindingEditDialogListener mListener;
private Binding[] mOtherBindings; private final ArrayList<Pair<String, ArrayList<Property>>> mProperties;
private Property mSelectedProperty; private Property mSelectedProperty;
private Button mTargetButton; private Button mTargetButton;
private EditText mFormulaEditText; private EditText mFormulaEditText;
private Button mEditButton; private Button mEditButton;
private Button mOkButton; private Button mOkButton;
private OnBindingEditDialogListener mListener;
private ArrayList<Pair<String,ArrayList<Property>>> mProperties;
public BindingEditDialog(Context context, Binding init_value, ItemView itemView, OnBindingEditDialogListener listener) { public BindingEditDialog(Context context, Binding init_value, ItemView itemView, OnBindingEditDialogListener listener) {
super(context); 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 // build the list of available properties minus the one already used
Class<? extends Item> itemClass = item.getClass(); 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<>(); 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<>(); 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) { for (Property p : pair_from.second) {
if(!isPropertyUsed(p.getName())) { if (!isPropertyUsed(p.getName())) {
available_properties.add(p); available_properties.add(p);
} }
} }
@ -105,11 +102,11 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
mProperties.add(pair_to); mProperties.add(pair_to);
} }
if(itemView.getClass() == ShortcutView.class) { if (itemView.getClass() == ShortcutView.class) {
IconLabelView il = ((ShortcutView) itemView).getIconLabelView(); IconLabelView il = ((ShortcutView) itemView).getIconLabelView();
if(il != null) { if (il != null) {
IconView iv = il.getIconView(); IconView iv = il.getIconView();
if(iv != null) { if (iv != null) {
addSvgProperties(R.string.svg_icon, "svg/icon/", mProperties, iv.getSharedAsyncGraphicsDrawable()); 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) { 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; return;
} }
SharedAsyncGraphicsDrawable sd = (SharedAsyncGraphicsDrawable) drawable; SharedAsyncGraphicsDrawable sd = (SharedAsyncGraphicsDrawable) drawable;
if(sd.getType() != SharedAsyncGraphicsDrawable.TYPE_SVG) { if (sd.getType() != SharedAsyncGraphicsDrawable.TYPE_SVG) {
return; return;
} }
@ -146,7 +143,7 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
String name = getContext().getString(nameRes); String name = getContext().getString(nameRes);
ArrayList<Property> properties = new ArrayList<>(); 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); 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); all_properties.add(pair);
} }
} }
private void addSvgPropertiesForElement(String prefix, SvgElement element, ArrayList<Property> properties) { private void addSvgPropertiesForElement(String prefix, SvgElement element, ArrayList<Property> properties) {
String id = element.getId(); String id = element.getId();
if(element instanceof SvgGroup) { if (element instanceof SvgGroup) {
for(SvgElement child : ((SvgGroup)element).getChildren()) { for (SvgElement child : ((SvgGroup) element).getChildren()) {
addSvgPropertiesForElement(prefix, child, properties); addSvgPropertiesForElement(prefix, child, properties);
} }
} }
if(id != null) { if (id != null) {
Context context = getContext(); Context context = getContext();
if(element instanceof SvgPath) { 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_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_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)); properties.add(new Property(context.getString(R.string.svgp_transform, id), prefix + id + "/transform", Property.TYPE_STRING));
} else if(element instanceof SvgGroup) { } else if (element instanceof SvgGroup) {
properties.add(new Property(context.getString(R.string.svgp_transform, id), prefix+id+"/transform", Property.TYPE_STRING)); 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) { protected void onCreate(Bundle savedInstanceState) {
View view = getLayoutInflater().inflate(R.layout.ll_pref_binding_dialog, null); 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_tt)).setText(R.string.bd_p);
((TextView)view.findViewById(R.id.bd_tf)).setText(R.string.bd_v); ((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); mSelectedProperty = mInitValue == null ? null : Property.getByName(mInitValue.target);
mTargetButton.setText(mSelectedProperty == null ? getContext().getString(R.string.bd_s) : mSelectedProperty.getLabel()); mTargetButton.setText(mSelectedProperty == null ? getContext().getString(R.string.bd_s) : mSelectedProperty.getLabel());
mTargetButton.setEnabled(mInitValue == null); mTargetButton.setEnabled(mInitValue == null);
mTargetButton.setOnClickListener(this); 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.setTypeface(LLApp.get().getIconsTypeface());
builtin.setOnClickListener(this); builtin.setOnClickListener(this);
mEditButton = (Button) view.findViewById(R.id.bd_fe); mEditButton = view.findViewById(R.id.bd_fe);
mEditButton.setTypeface(LLApp.get().getIconsTypeface()); mEditButton.setTypeface(LLApp.get().getIconsTypeface());
mEditButton.setOnClickListener(this); mEditButton.setOnClickListener(this);
mEditButton.setEnabled(mInitValue != null); mEditButton.setEnabled(mInitValue != null);
mFormulaEditText = (EditText) view.findViewById(R.id.bd_f); mFormulaEditText = view.findViewById(R.id.bd_f);
if(mInitValue != null) { if (mInitValue != null) {
mFormulaEditText.setText(mInitValue.formula); mFormulaEditText.setText(mInitValue.formula);
} }
@ -248,14 +245,15 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
} }
private void save(boolean open_in_script_editor) { private void save(boolean open_in_script_editor) {
String target =mSelectedProperty.getName(); String target = mSelectedProperty.getName();
String formula = mFormulaEditText.getText().toString(); 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); mListener.onBindingEdited(binding, open_in_script_editor);
} }
private static final String ROOT_KEY = "r"; public interface OnBindingEditDialogListener {
private static final String CHILD_KEY = "c"; void onBindingEdited(Binding binding, boolean open_in_script_editor);
}
private class PropertySelectionDialog extends Dialog implements ExpandableListView.OnChildClickListener { 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<Map<String, String>> groupData = new ArrayList<>();
List<List<Map<String, String>>> childData = 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<>(); HashMap<String, String> value = new HashMap<>();
value.put(ROOT_KEY, category.first); value.put(ROOT_KEY, category.first);
groupData.add(value); groupData.add(value);
List<Map<String, String>> child_values = new ArrayList<>(); 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<>(); HashMap<String, String> child_value = new HashMap<>();
child_value.put(CHILD_KEY, p.getLabel()); child_value.put(CHILD_KEY, p.getLabel());
child_values.add(child_value); child_values.add(child_value);
@ -292,13 +290,13 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
groupData, groupData,
android.R.layout.simple_expandable_list_item_1, android.R.layout.simple_expandable_list_item_1,
new String[] { ROOT_KEY }, new String[]{ROOT_KEY},
new int[] { android.R.id.text1 }, new int[]{android.R.id.text1},
childData, childData,
android.R.layout.simple_expandable_list_item_1, android.R.layout.simple_expandable_list_item_1,
new String[] { CHILD_KEY }, new String[]{CHILD_KEY},
new int[] { android.R.id.text1 } new int[]{android.R.id.text1}
); );
list.setAdapter(adapter); list.setAdapter(adapter);
@ -319,7 +317,7 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
private class VariableSelectionDialog extends Dialog implements ExpandableListView.OnChildClickListener { private class VariableSelectionDialog extends Dialog implements ExpandableListView.OnChildClickListener {
private SimpleExpandableListAdapter mAdapter; private SimpleExpandableListAdapter mAdapter;
private Pair<String,BuiltinVariable[]>[] mBuiltinVariables; private Pair<String, BuiltinVariable[]>[] mBuiltinVariables;
private ArrayList<Variable> mUserVariables; private ArrayList<Variable> mUserVariables;
public VariableSelectionDialog(Context context) { public VariableSelectionDialog(Context context) {
@ -343,13 +341,13 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
List<Map<String, String>> groupData = new ArrayList<>(); List<Map<String, String>> groupData = new ArrayList<>();
List<List<Map<String, String>>> childData = 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<>(); HashMap<String, String> value = new HashMap<>();
value.put(ROOT_KEY, category.first); value.put(ROOT_KEY, category.first);
groupData.add(value); groupData.add(value);
List<Map<String, String>> child_values = new ArrayList<>(); 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<>(); HashMap<String, String> child_value = new HashMap<>();
child_value.put(CHILD_KEY, bv.label); child_value.put(CHILD_KEY, bv.label);
child_values.add(child_value); child_values.add(child_value);
@ -362,7 +360,7 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
groupData.add(value); groupData.add(value);
List<Map<String, String>> child_values = new ArrayList<>(); List<Map<String, String>> child_values = new ArrayList<>();
for(Variable v : mUserVariables) { for (Variable v : mUserVariables) {
HashMap<String, String> child_value = new HashMap<>(); HashMap<String, String> child_value = new HashMap<>();
child_value.put(CHILD_KEY, v.name); child_value.put(CHILD_KEY, v.name);
child_values.add(child_value); child_values.add(child_value);
@ -370,19 +368,18 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
childData.add(child_values); childData.add(child_values);
mAdapter = new SimpleExpandableListAdapter( mAdapter = new SimpleExpandableListAdapter(
getContext(), getContext(),
groupData, groupData,
android.R.layout.simple_expandable_list_item_1, android.R.layout.simple_expandable_list_item_1,
new String[] { ROOT_KEY }, new String[]{ROOT_KEY},
new int[] { android.R.id.text1 }, new int[]{android.R.id.text1},
childData, childData,
android.R.layout.simple_expandable_list_item_1, android.R.layout.simple_expandable_list_item_1,
new String[] { CHILD_KEY }, new String[]{CHILD_KEY},
new int[] { android.R.id.text1 } new int[]{android.R.id.text1}
); );
list.setAdapter(mAdapter); list.setAdapter(mAdapter);
@ -393,14 +390,14 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
@Override @Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
String name; String name;
if(groupPosition < mBuiltinVariables.length) { if (groupPosition < mBuiltinVariables.length) {
name = mBuiltinVariables[groupPosition].second[childPosition].name; name = mBuiltinVariables[groupPosition].second[childPosition].name;
} else { } else {
name = mUserVariables.get(childPosition).name; name = mUserVariables.get(childPosition).name;
} }
int selstart = mFormulaEditText.getSelectionStart(); int selstart = mFormulaEditText.getSelectionStart();
int selend = mFormulaEditText.getSelectionEnd(); 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(); dismiss();
return true; return true;
} }

View file

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

View file

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

View file

@ -42,107 +42,36 @@ import java.util.Map;
*/ */
public class Indentation { public class Indentation {
private static final int INDENT_SIZE = 2; private static final int INDENT_SIZE = 2;
private Map<EditText, IndentationTextWatcher> mRegistered = new HashMap<>(); private final 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 -----------------
/** /**
* Returns the size of the indent in the current line (spaces at the left) and the position of the first non-space char * 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 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) * @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 // goto beginning of line
if(currentpos != 0) { if (currentpos != 0) {
do{ do {
currentpos--; currentpos--;
}while (currentpos >= 0 && editable.charAt(currentpos) != '\n'); } while (currentpos >= 0 && editable.charAt(currentpos) != '\n');
currentpos++; currentpos++;
} }
// find indent size // find indent size
int n = 0; int n = 0;
boolean cont = true; boolean cont = true;
while(cont && currentpos < editable.length()){ while (cont && currentpos < editable.length()) {
switch (editable.charAt(currentpos)){ switch (editable.charAt(currentpos)) {
case ' ': case ' ':
n++; n++;
currentpos++; currentpos++;
break; break;
case '\t': case '\t':
n+=INDENT_SIZE; n += INDENT_SIZE;
currentpos++; currentpos++;
break; break;
//case '\n': //case '\n':
@ -152,69 +81,72 @@ public class Indentation {
} }
return new Pair<>(n, currentpos); return new Pair<>(n, currentpos);
} }
/** /**
* Changes the indentation of all the lines selected * Changes the indentation of all the lines selected
* @param posLeft start of selection *
* @param posLeft start of selection
* @param posRight end of selection * @param posRight end of selection
* @param increase if true increase indent, decrease otherwise * @param increase if true increase indent, decrease otherwise
* @param editable where to apply the indentation * @param editable where to apply the indentation
* @return the new selection (may have changed due to the indentation changes) * @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"; String span = "modifyIntent";
editable.setSpan(span, posLeft, posRight, Spanned.SPAN_EXCLUSIVE_INCLUSIVE); editable.setSpan(span, posLeft, posRight, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
Deque<Integer> positions = new ArrayDeque<>(); Deque<Integer> positions = new ArrayDeque<>();
while(posLeft <= posRight && posLeft <= editable.length()){ while (posLeft <= posRight && posLeft <= editable.length()) {
// mark position to indent // mark position to indent
positions.push(posLeft); positions.push(posLeft);
// find next line (next newline char) // find next line (next newline char)
posLeft++; posLeft++;
while(posLeft <= posRight && posLeft <= editable.length() && editable.charAt(posLeft - 1) != '\n') while (posLeft <= posRight && posLeft <= editable.length() && editable.charAt(posLeft - 1) != '\n')
posLeft++; posLeft++;
} }
for (Integer position : positions) { for (Integer position : positions) {
// indent the lines in reverse order // indent the lines in reverse order
if(increase) if (increase)
increaseIndent(position, editable); increaseIndent(position, editable);
else else
decreaseIndent(position, editable); decreaseIndent(position, editable);
} }
//restore span //restore span
return new Pair<>(editable.getSpanStart(span), editable.getSpanEnd(span)); return new Pair<>(editable.getSpanStart(span), editable.getSpanEnd(span));
} }
/** /**
* Increases the indentation of a single line * Increases the indentation of a single line
*
* @param posCursor position of a character in the line that will be indented * @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); Pair<Integer, Integer> n_beg = getLineIndent(posCursor, editable);
int beg = n_beg.second; int beg = n_beg.second;
// increase indent adding spaces // 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 * Decreases the indentation of a single line
*
* @param posCursor position of a character in the line that will be indented * @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); Pair<Integer, Integer> n_beg = getLineIndent(posCursor, editable);
int n = n_beg.first; int n = n_beg.first;
int beg = n_beg.second; 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 // enough intent to remove, remove the first tab, or all the spaces if no tabs found
int p = 1; int p = 1;
while (p <= INDENT_SIZE) { while (p <= INDENT_SIZE) {
@ -227,61 +159,134 @@ public class Indentation {
} }
// no tabs found, only spaces, remove them // no tabs found, only spaces, remove them
editable.delete(beg - INDENT_SIZE, beg); editable.delete(beg - INDENT_SIZE, beg);
}else{ } else {
// not enough indent (so no tabs), just remove all the previous spaces // not enough indent (so no tabs), just remove all the previous spaces
editable.delete(beg - n, beg); 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 ---------------- // ------------ textwatcher ----------------
private class IndentationTextWatcher implements 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) { IndentationTextWatcher(EditText mEditText) {
this.mEditText = mEditText; this.mEditText = mEditText;
} }
private String mSpanNewline = "mSpanNewline";
private String mSpanEndBracket = "mSpanEndBracket";
private boolean mEditing = false;
private EditText mEditText;
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
} }
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
if(mEditing) return; if (mEditing) return;
if(count == 1 && s.charAt(start) == '\n'){ if (count == 1 && s.charAt(start) == '\n') {
// newline inserted // 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 // end bracket inserted
mEditText.getEditableText().setSpan(mSpanEndBracket, start, start, 0); mEditText.getEditableText().setSpan(mSpanEndBracket, start, start, 0);
} }
} }
@Override @Override
public void afterTextChanged(Editable editable) { public void afterTextChanged(Editable editable) {
mEditing = true; mEditing = true;
int spanPos; int spanPos;
// check newline // check newline
spanPos = editable.getSpanStart(mSpanNewline); spanPos = editable.getSpanStart(mSpanNewline);
editable.removeSpan(mSpanNewline); editable.removeSpan(mSpanNewline);
if (spanPos != -1 && editable.charAt(spanPos) == '\n') if (spanPos != -1 && editable.charAt(spanPos) == '\n')
onNewLine(spanPos, editable); onNewLine(spanPos, editable);
// check endbracket // check endbracket
spanPos = editable.getSpanStart(mSpanEndBracket); spanPos = editable.getSpanStart(mSpanEndBracket);
editable.removeSpan(mSpanEndBracket); editable.removeSpan(mSpanEndBracket);
if (spanPos != -1 && editable.charAt(spanPos) == '}') if (spanPos != -1 && editable.charAt(spanPos) == '}')
onEndBracket(spanPos, editable); onEndBracket(spanPos, editable);
mEditing = false; mEditing = false;
} }
} }

View file

@ -72,7 +72,7 @@ public class LightningLWPService extends WallpaperService {
@Override @Override
public final Resources getResources() { public final Resources getResources() {
if(mResourcesWrapperHelper == null) { if (mResourcesWrapperHelper == null) {
mResourcesWrapperHelper = new ResourcesWrapperHelper(this, super.getResources()); mResourcesWrapperHelper = new ResourcesWrapperHelper(this, super.getResources());
} }
return mResourcesWrapperHelper.getResources(); return mResourcesWrapperHelper.getResources();
@ -104,15 +104,15 @@ public class LightningLWPService extends WallpaperService {
LightningEngine lightningEngine = app.getAppEngine(); LightningEngine lightningEngine = app.getAppEngine();
lightningEngine.registerGlobalConfigChangeListener(this); lightningEngine.registerGlobalConfigChangeListener(this);
final GlobalConfig globalConfig = lightningEngine.getGlobalConfig(); final GlobalConfig globalConfig = lightningEngine.getGlobalConfig();
mLWPDesktopId =globalConfig.lwpScreen; mLWPDesktopId = globalConfig.lwpScreen;
mScreen = new LightningLWPScreen(LightningLWPService.this, R.layout.lwp); mScreen = new LightningLWPScreen(LightningLWPService.this, R.layout.lwp);
mContentView = (EventFrameLayout) mScreen.getContentView(); mContentView = (EventFrameLayout) mScreen.getContentView();
mItemLayout = (ItemLayout) mContentView.findViewById(R.id.lwp_il); mItemLayout = mContentView.findViewById(R.id.lwp_il);
mScreen.takeItemLayoutOwnership(mItemLayout); mScreen.takeItemLayoutOwnership(mItemLayout);
mNoDesktopView = (TextView) mContentView.findViewById(R.id.empty); mNoDesktopView = mContentView.findViewById(R.id.empty);
mNoDesktopView.setText(R.string.sd); mNoDesktopView.setText(R.string.sd);
mNoDesktopView.setOnClickListener(new View.OnClickListener() { mNoDesktopView.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -125,14 +125,14 @@ public class LightningLWPService extends WallpaperService {
IBinder token = null; IBinder token = null;
final Field[] declaredFields = getClass().getSuperclass().getDeclaredFields(); final Field[] declaredFields = getClass().getSuperclass().getDeclaredFields();
for (Field f : declaredFields) { for (Field f : declaredFields) {
if(f.getName().equals("mWindowToken")) { if (f.getName().equals("mWindowToken")) {
f.setAccessible(true); f.setAccessible(true);
token = (IBinder) f.get(this); token = (IBinder) f.get(this);
break; break;
} }
} }
if(token != null) { if (token != null) {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams attrs = new WindowManager.LayoutParams( WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@ -184,7 +184,7 @@ public class LightningLWPService extends WallpaperService {
mScreen.setCustomScreenSize(width, height); mScreen.setCustomScreenSize(width, height);
if(!mUseWindow) { if (!mUseWindow) {
layout(); layout();
draw(); draw();
} }
@ -192,7 +192,7 @@ public class LightningLWPService extends WallpaperService {
@Override @Override
public void onSurfaceRedrawNeeded(SurfaceHolder holder) { public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
if(!mUseWindow) { if (!mUseWindow) {
draw(); draw();
} }
} }
@ -200,9 +200,9 @@ public class LightningLWPService extends WallpaperService {
@Override @Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
Rect boundingBox = mItemLayout.getItemsBoundingBox(); Rect boundingBox = mItemLayout.getItemsBoundingBox();
float x = xOffset*(mItemLayout.getWidth()-boundingBox.width()) - boundingBox.left; float x = xOffset * (mItemLayout.getWidth() - boundingBox.width()) - boundingBox.left;
float y = yOffset*(mItemLayout.getHeight()-boundingBox.height()) - boundingBox.top; float y = yOffset * (mItemLayout.getHeight() - boundingBox.height()) - boundingBox.top;
if(mItemLayout.getCurrentX() != x || mItemLayout.getCurrentY() != y) { if (mItemLayout.getCurrentX() != x || mItemLayout.getCurrentY() != y) {
mItemLayout.moveTo(x, y, 1); 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) { public Bundle onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested) {
boolean isTap = WallpaperManager.COMMAND_TAP.equals(action); boolean isTap = WallpaperManager.COMMAND_TAP.equals(action);
boolean isSecondaryTap = WallpaperManager.COMMAND_SECONDARY_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]; int[] offset = new int[2];
mContentView.getLocationOnScreen(offset); mContentView.getLocationOnScreen(offset);
x -= offset[0]; x -= offset[0];
y -= offset[1]; y -= offset[1];
if(mUseWindow) { if (mUseWindow) {
boolean dispatch = mContentView.getDispatchEvent(); boolean dispatch = mContentView.getDispatchEvent();
mContentView.setDispatchEvent(true); mContentView.setDispatchEvent(true);
@ -229,11 +229,11 @@ public class LightningLWPService extends WallpaperService {
mContentView.dispatchTouchEvent(event); mContentView.dispatchTouchEvent(event);
mContentView.setDispatchEvent(dispatch); 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 // 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(); Rect r = new Rect();
mNoDesktopView.getHitRect(r); mNoDesktopView.getHitRect(r);
if(r.contains(x, y)) { if (r.contains(x, y)) {
startSettings(); startSettings();
} }
} }
@ -269,9 +269,9 @@ public class LightningLWPService extends WallpaperService {
} }
private void setVisibility(boolean visible) { private void setVisibility(boolean visible) {
if(visible != mVisible) { if (visible != mVisible) {
mVisible = visible; mVisible = visible;
if(mVisible) { if (mVisible) {
mScreen.resume(); mScreen.resume();
} else { } else {
mScreen.pause(); mScreen.pause();
@ -280,7 +280,7 @@ public class LightningLWPService extends WallpaperService {
} }
private void configurePage() { private void configurePage() {
if(!((LLAppExtreme)LLApp.get()).hasLWP()) { if (!((LLAppExtreme) LLApp.get()).hasLWP()) {
mLWPDesktopId = Page.NONE; mLWPDesktopId = Page.NONE;
} }
boolean hasPage = mLWPDesktopId != Page.NONE; boolean hasPage = mLWPDesktopId != Page.NONE;
@ -296,11 +296,11 @@ public class LightningLWPService extends WallpaperService {
@Override @Override
public void onGlobalConfigChanged(GlobalConfig newGlobalConfig) { public void onGlobalConfigChanged(GlobalConfig newGlobalConfig) {
if(newGlobalConfig.lwpScreen != mLWPDesktopId) { if (newGlobalConfig.lwpScreen != mLWPDesktopId) {
mLWPDesktopId = newGlobalConfig.lwpScreen; mLWPDesktopId = newGlobalConfig.lwpScreen;
configurePage(); configurePage();
if(!mUseWindow) { if (!mUseWindow) {
layout(); layout();
draw(); draw();
} }
@ -324,7 +324,7 @@ public class LightningLWPService extends WallpaperService {
@Override @Override
public void goToDesktopPosition(int page, float x, float y, float s, boolean animate, boolean absolute) { 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(); LightningEngine engine = mMainPage.getEngine();
engine.getGlobalConfig().lwpScreen = page; engine.getGlobalConfig().lwpScreen = page;
engine.notifyGlobalConfigChanged(); engine.notifyGlobalConfigChanged();
@ -340,7 +340,7 @@ public class LightningLWPService extends WallpaperService {
@Override @Override
public ItemLayout loadRootItemLayout(int page, boolean reset_navigation_history, boolean displayImmediately, boolean animate) { 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; return mItemLayout;
} else { } else {
return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate); return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate);
@ -380,7 +380,7 @@ public class LightningLWPService extends WallpaperService {
public void onPageModified(Page page) { public void onPageModified(Page page) {
super.onPageModified(page); super.onPageModified(page);
if(page == mMainPage) { if (page == mMainPage) {
mContentView.setDispatchEvent(page.config.lwpStdEvents); mContentView.setDispatchEvent(page.config.lwpStdEvents);
} }
} }
@ -389,7 +389,7 @@ public class LightningLWPService extends WallpaperService {
public void setVisibility(boolean visible) { public void setVisibility(boolean visible) {
int oldVisibility = mContentView.getVisibility(); int oldVisibility = mContentView.getVisibility();
int newVisibility = visible ? View.VISIBLE : View.GONE; int newVisibility = visible ? View.VISIBLE : View.GONE;
if(oldVisibility != newVisibility) { if (oldVisibility != newVisibility) {
mContentView.setVisibility(newVisibility); mContentView.setVisibility(newVisibility);
mContentView.startAnimation(AnimationUtils.loadAnimation(LightningLWPService.this, visible ? android.R.anim.fade_in : android.R.anim.fade_out)); 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 android.widget.TextView;
import net.pierrox.lightning_launcher.LLApp; 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.activities.ScriptEditor;
import net.pierrox.lightning_launcher.data.Utils; import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.engine.LightningEngine; import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.script.Script; import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.script.ScriptManager; import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher_extreme.R;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnItemSelectedListener { public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnItemSelectedListener {
private static boolean sShowSubDirs;
private static File sCurrentDirectory;
private final CheckBox mHasDataCheckBox; private final CheckBox mHasDataCheckBox;
private final EditText mDataTextView; private final EditText mDataTextView;
private final Spinner mTargetsSpinner; private final Spinner mTargetsSpinner;
private final Spinner mScriptSpinner; private final Spinner mScriptSpinner;
private Button mSelectDirectoryButton; private final Button mSelectDirectoryButton;
private ArrayAdapter<Script> mScriptAdapter; private final ArrayAdapter<Script> mScriptAdapter;
private ArrayList<Script> mAllScripts; private final ArrayList<Script> mAllScripts;
private final ScriptManager mScriptManager; private final ScriptManager mScriptManager;
private final int mInitialTarget;
private final OnScriptPickerEvent mListener;
private Script mScript; 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) { public ScriptPickerDialog(final Context context, LightningEngine engine, String initial_id_data, final int initial_target, final OnScriptPickerEvent listener) {
super(context); super(context);
@ -82,36 +74,36 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
mListener = listener; mListener = listener;
mScriptManager = engine.getScriptManager(); mScriptManager = engine.getScriptManager();
if(sCurrentDirectory == null) { if (sCurrentDirectory == null) {
sCurrentDirectory = mScriptManager.getScriptsDir(); sCurrentDirectory = mScriptManager.getScriptsDir();
} }
mAllScripts = mScriptManager.getAllScriptMatching(Script.FLAG_ALL); mAllScripts = mScriptManager.getAllScriptMatching(Script.FLAG_ALL);
setTitle(R.string.sst); 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); setView(content);
mScriptSpinner = (Spinner) content.findViewById(R.id.script); mScriptSpinner = content.findViewById(R.id.script);
mTargetsSpinner = (Spinner) content.findViewById(R.id.tg); mTargetsSpinner = content.findViewById(R.id.tg);
final Button sc_new = (Button) content.findViewById(R.id.sc_new); final Button sc_new = content.findViewById(R.id.sc_new);
mHasDataCheckBox = (CheckBox) content.findViewById(R.id.has_data); mHasDataCheckBox = content.findViewById(R.id.has_data);
mDataTextView = (EditText) content.findViewById(R.id.data); mDataTextView = content.findViewById(R.id.data);
((TextView)content.findViewById(R.id.tgt)).setText(R.string.tg); ((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_path)).setText(R.string.sc_path);
((TextView)content.findViewById(R.id.sc_name)).setText(R.string.sc_name); ((TextView) content.findViewById(R.id.sc_name)).setText(R.string.sc_name);
sc_new.setText(R.string.sc_new); 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.setTypeface(LLApp.get().getIconsTypeface());
editButton.setOnClickListener(new View.OnClickListener() { editButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if(mScript != null) { if (mScript != null) {
ScriptEditor.startActivity(context, mScript.id, 1); 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() { mSelectDirectoryButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -121,7 +113,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
sCurrentDirectory = file; sCurrentDirectory = file;
updateSelectDirectoryButton(); updateSelectDirectoryButton();
updateScriptsSpinner(); updateScriptsSpinner();
if(!mAllScripts.contains(mScript) && mAllScripts.size() > 0) { if (!mAllScripts.contains(mScript) && mAllScripts.size() > 0) {
mScript = mAllScripts.get(0); mScript = mAllScripts.get(0);
} }
} }
@ -130,7 +122,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
}); });
updateSelectDirectoryButton(); 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.setText(R.string.sc_all);
showSubDirs.setChecked(sShowSubDirs); showSubDirs.setChecked(sShowSubDirs);
showSubDirs.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { showSubDirs.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@ -138,7 +130,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
sShowSubDirs = isChecked; sShowSubDirs = isChecked;
updateScriptsSpinner(); updateScriptsSpinner();
if(!mAllScripts.contains(mScript) && mAllScripts.size() > 0) { if (!mAllScripts.contains(mScript) && mAllScripts.size() > 0) {
mScript = mAllScripts.get(0); mScript = mAllScripts.get(0);
} }
} }
@ -167,7 +159,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
mScriptSpinner.requestFocus(); mScriptSpinner.requestFocus();
View targets_group = content.findViewById(R.id.tgg); View targets_group = content.findViewById(R.id.tgg);
if(mInitialTarget == Script.TARGET_NONE) { if (mInitialTarget == Script.TARGET_NONE) {
targets_group.setVisibility(View.GONE); targets_group.setVisibility(View.GONE);
} else { } else {
String[] target_names = new String[]{ String[] target_names = new String[]{
@ -187,23 +179,23 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mDataTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE); mDataTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
if(isChecked) mDataTextView.requestFocus(); if (isChecked) mDataTextView.requestFocus();
else mDataTextView.clearFocus(); else mDataTextView.clearFocus();
} }
}); });
if(initial_id_data != null) { if (initial_id_data != null) {
final Pair<Integer, String> pair = Script.decodeIdAndData(initial_id_data); final Pair<Integer, String> pair = Script.decodeIdAndData(initial_id_data);
mScript = mScriptManager.getOrLoadScript(pair.first); mScript = mScriptManager.getOrLoadScript(pair.first);
if(mScript != null) { if (mScript != null) {
if (sShowSubDirs) { if (sShowSubDirs) {
File root = mScriptManager.getScriptsDir(); File root = mScriptManager.getScriptsDir();
for(;;) { for (; ; ) {
updateScriptsSpinner(); updateScriptsSpinner();
if(sCurrentDirectory.equals(root)) { if (sCurrentDirectory.equals(root)) {
break; break;
} }
if(mAllScripts.contains(mScript)) { if (mAllScripts.contains(mScript)) {
break; break;
} }
@ -275,18 +267,18 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
private void updateScriptsSpinner() { private void updateScriptsSpinner() {
ArrayList<Script> allScripts = mScriptManager.getAllScriptMatching(Script.FLAG_ALL); ArrayList<Script> allScripts = mScriptManager.getAllScriptMatching(Script.FLAG_ALL);
String currentPath = mScriptManager.getRelativePath(sCurrentDirectory); 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) // ensure a trailing slash to avoid false match (like /ab and /ac whith current = /a)
currentPath += "/"; currentPath += "/";
} }
mAllScripts.clear(); mAllScripts.clear();
for (Script script : allScripts) { for (Script script : allScripts) {
if(script.getType() == Script.TYPE_FILE) { if (script.getType() == Script.TYPE_FILE) {
String relativePath = script.getRelativePath(); String relativePath = script.getRelativePath();
if(!relativePath.endsWith("/")) { if (!relativePath.endsWith("/")) {
relativePath += "/"; relativePath += "/";
} }
if((sShowSubDirs && relativePath.startsWith(currentPath)) || relativePath.equals(currentPath)) { if ((sShowSubDirs && relativePath.startsWith(currentPath)) || relativePath.equals(currentPath)) {
mAllScripts.add(script); mAllScripts.add(script);
} }
} }
@ -295,7 +287,7 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
mScriptAdapter.notifyDataSetChanged(); mScriptAdapter.notifyDataSetChanged();
int position = mAllScripts.indexOf(mScript); int position = mAllScripts.indexOf(mScript);
if(position != -1) { if (position != -1) {
mScriptSpinner.setSelection(position); mScriptSpinner.setSelection(position);
} }
} }
@ -303,4 +295,11 @@ public class ScriptPickerDialog extends AlertDialog implements AdapterView.OnIte
private void updateSelectDirectoryButton() { private void updateSelectDirectoryButton() {
mSelectDirectoryButton.setText(mScriptManager.getRelativePath(sCurrentDirectory)); 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). * Class that Manages a searchable dialog (currently for the script editor).
*/ */
public class Search { public class Search {
private Activity mCntx; private final Activity mCntx;
private AdvancedEditText mEditText; private final AdvancedEditText mEditText;
private AlertDialog mDialog; private AlertDialog mDialog;
private EditText mEdTxt; private EditText mEdTxt;
private CheckBox mChkBackwards; private CheckBox mChkBackwards;
private CheckBox mChkCase; private CheckBox mChkCase;
private CheckBox mChkRegexp; private CheckBox mChkRegexp;
public Search(Activity cntx, AdvancedEditText editText) { public Search(Activity cntx, AdvancedEditText editText) {
mCntx = cntx; mCntx = cntx;
mEditText = editText; mEditText = editText;
// The dialog is saved and created on first use // The dialog is saved and created on first use
mDialog = null; mDialog = null;
} }
/** /**
* Shows the dialog to search. * Shows the dialog to search.
*/ */
public void showDialog(){ public void showDialog() {
if(mDialog == null) if (mDialog == null)
createDialog(); createDialog();
mDialog.show(); mDialog.show();
} }
/** /**
* Performs a search as defined in the dialog. * Performs a search as defined in the dialog.
* If the search fails the dialog is shown. * If the search fails the dialog is shown.
*/ */
public void searchNext() { public void searchNext() {
if(mDialog == null) if (mDialog == null)
createDialog(); createDialog();
String searchText = mEdTxt.getText().toString(); String searchText = mEdTxt.getText().toString();
if(searchText.isEmpty()) { if (searchText.isEmpty()) {
// no text to search // no text to search
showDialog(); showDialog();
return; return;
} }
String text = mEditText.getText().toString(); String text = mEditText.getText().toString();
int flags = 0; int flags = 0;
if(!mChkCase.isChecked()) flags |= Pattern.CASE_INSENSITIVE; if (!mChkCase.isChecked()) flags |= Pattern.CASE_INSENSITIVE;
if(!mChkRegexp.isChecked()) flags |= Pattern.LITERAL; if (!mChkRegexp.isChecked()) flags |= Pattern.LITERAL;
Pattern pattern = Pattern.compile(searchText, flags); Pattern pattern = Pattern.compile(searchText, flags);
int start = -1; int start = -1;
int end = -1; int end = -1;
Matcher matcher = pattern.matcher(text); Matcher matcher = pattern.matcher(text);
if(!mChkBackwards.isChecked()) { if (!mChkBackwards.isChecked()) {
// search fordwards // search fordwards
int from = mEditText.getTrueSelectionStart(); int from = mEditText.getTrueSelectionStart();
if (from != mEditText.getTrueSelectionEnd()) from++; // avoids returning the current selection if (from != mEditText.getTrueSelectionEnd())
if( matcher.find(from) || matcher.find(0)){ from++; // avoids returning the current selection
if (matcher.find(from) || matcher.find(0)) {
// found one just after the selection or from the beginning // found one just after the selection or from the beginning
start = matcher.start(); start = matcher.start();
end = matcher.end(); end = matcher.end();
} }
}else{ } else {
// search backwards // search backwards
int until = mEditText.getTrueSelectionEnd(); int until = mEditText.getTrueSelectionEnd();
while( matcher.find() && matcher.end() < until){ while (matcher.find() && matcher.end() < until) {
// found match before cursor, save // found match before cursor, save
start = matcher.start(); start = matcher.start();
end = matcher.end(); end = matcher.end();
} }
if(start == -1){ if (start == -1) {
// not found, continue to find last one // not found, continue to find last one
while( matcher.find() ){ while (matcher.find()) {
// found match, save // found match, save
start = matcher.start(); start = matcher.start();
end = matcher.end(); end = matcher.end();
} }
} }
} }
if( start != -1) { if (start != -1) {
// found, set selection // found, set selection
mEditText.setSelection(start, end); mEditText.setSelection(start, end);
}else{ } else {
// nothing found // nothing found
showDialog(); showDialog();
} }
} }
/** /**
* Private: creates the dialog * Private: creates the dialog
*/ */
private void createDialog(){ private void createDialog() {
View views = mCntx.getLayoutInflater().inflate(R.layout.dialog_search, null); View views = mCntx.getLayoutInflater().inflate(R.layout.dialog_search, null);
mEdTxt = views.findViewById(R.id.srch_text); mEdTxt = views.findViewById(R.id.srch_text);
mChkBackwards = views.findViewById(R.id.srch_back); mChkBackwards = views.findViewById(R.id.srch_back);
mChkCase = views.findViewById(R.id.srch_case); mChkCase = views.findViewById(R.id.srch_case);
mChkRegexp = views.findViewById(R.id.srch_regexp); mChkRegexp = views.findViewById(R.id.srch_regexp);
mDialog = new AlertDialog.Builder(mCntx) mDialog = new AlertDialog.Builder(mCntx)
.setTitle(R.string.srch_ttl) .setTitle(R.string.srch_ttl)
.setView(views) .setView(views)

View file

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

View file

@ -34,7 +34,6 @@ import android.graphics.Color;
import android.graphics.Rect; import android.graphics.Rect;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.util.DisplayMetrics; 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.LightningIntent;
import net.pierrox.lightning_launcher.data.Page; import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.PageIndicator; 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.PageProcessor;
import net.pierrox.lightning_launcher.data.Shortcut; import net.pierrox.lightning_launcher.data.Shortcut;
import net.pierrox.lightning_launcher.data.Utils; 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.script.ScriptManager;
import net.pierrox.lightning_launcher_extreme.BuildConfig; import net.pierrox.lightning_launcher_extreme.BuildConfig;
import net.pierrox.lightning_launcher_extreme.R; import net.pierrox.lightning_launcher_extreme.R;
@ -73,17 +72,53 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
public class Setup { public class Setup {
public interface OnFirstTimeInitEvent { private static final String[] CN_DOCK_0 = new String[]{
public void onFirstTimeInitStart(boolean is_import); // phone
public void onFirstTimeInitEnd(boolean success, boolean was_import, Item all_apps_item); "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") @SuppressWarnings("deprecation")
public static void firstTimeInit(final OnFirstTimeInitEvent listener) { public static void firstTimeInit(final OnFirstTimeInitEvent listener) {
final LightningEngine engine = LLApp.get().getAppEngine(); final LightningEngine engine = LLApp.get().getAppEngine();
Context tmp = null; Context tmp = null;
if(!BuildConfig.IS_TRIAL) { if (!BuildConfig.IS_TRIAL) {
try { try {
tmp = LLApp.get().createPackageContext(LLApp.LL_PKG_NAME, 0); tmp = LLApp.get().createPackageContext(LLApp.LL_PKG_NAME, 0);
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
@ -104,7 +139,7 @@ public class Setup {
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
was_import = import_data; was_import = import_data;
if(!import_data) { if (!import_data) {
try { try {
Thread.sleep(4000); Thread.sleep(4000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -122,7 +157,7 @@ public class Setup {
// ll is here but no valid data // ll is here but no valid data
engine.reloadGlobalConfig(); engine.reloadGlobalConfig();
if(engine.shouldDoFirstTimeInit()) { if (engine.shouldDoFirstTimeInit()) {
was_import = false; was_import = false;
mAllAppsItem = defaultSetup(engine); mAllAppsItem = defaultSetup(engine);
return true; return true;
@ -131,7 +166,7 @@ public class Setup {
LightningEngine.PageManager pageManager = engine.getPageManager(); LightningEngine.PageManager pageManager = engine.getPageManager();
pageManager.clear(); pageManager.clear();
ArrayList<Page> mImportedPages = new ArrayList<>(); ArrayList<Page> mImportedPages = new ArrayList<>();
for(int p : pageManager.getAllPagesIds()) { for (int p : pageManager.getAllPagesIds()) {
mImportedPages.add(pageManager.getOrLoadPage(p)); 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) { private static Item defaultSetup(LightningEngine engine) {
File dir = engine.getBaseDir(); File dir = engine.getBaseDir();
if(!dir.exists()) { if (!dir.exists()) {
dir.mkdirs(); dir.mkdirs();
} }
Utils.deleteDirectory(dir, false); Utils.deleteDirectory(dir, false);
@ -219,8 +212,8 @@ public class Setup {
GlobalConfig globalConfig = engine.getGlobalConfig(); GlobalConfig globalConfig = engine.getGlobalConfig();
if(!BuildConfig.IS_TRIAL || LLApp.get().isTrialVersion()) { if (!BuildConfig.IS_TRIAL || LLApp.get().isTrialVersion()) {
Page lockscreen = engine.getOrLoadPage(Page.FIRST_DASHBOARD_PAGE+1); Page lockscreen = engine.getOrLoadPage(Page.FIRST_DASHBOARD_PAGE + 1);
setupLockScreen(lockscreen); setupLockScreen(lockscreen);
globalConfig.screensOrder = new int[2]; globalConfig.screensOrder = new int[2];
@ -234,7 +227,7 @@ public class Setup {
} }
// create dashboard default config // create dashboard default config
int page= Page.FIRST_DASHBOARD_PAGE; int page = Page.FIRST_DASHBOARD_PAGE;
Page dashboard = pm.getOrLoadPage(page); Page dashboard = pm.getOrLoadPage(page);
Item all_apps_item = setupDashboard(dashboard, drawer); 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); int color_primary_dark = resources.getColor(R.color.color_primary_dark);
final PageConfig dashboard_config = dashboard.config; final PageConfig dashboard_config = dashboard.config;
dashboard_config.applyDefaultFolderConfig(); dashboard_config.applyDefaultFolderConfig();
dashboard_config.defaultFolderConfig.outsideTapClose = true; dashboard_config.defaultFolderConfig.outsideTapClose = true;
@ -302,7 +294,7 @@ public class Setup {
ic.box_s = ic.box.toString(dashboard_config.defaultItemConfig.box); ic.box_s = ic.box.toString(dashboard_config.defaultItemConfig.box);
pi.notifyChanged(); pi.notifyChanged();
if(!LLApp.get().isFreeVersion()) { if (!LLApp.get().isFreeVersion()) {
// install date and time dynamic texts // install date and time dynamic texts
DynamicText dt = Utils.addDynamicText(dashboard, DynamicTextConfig.Source.DATE, true); DynamicText dt = Utils.addDynamicText(dashboard, DynamicTextConfig.Source.DATE, true);
dt.getCell().set(3, 4, 5, 5); dt.getCell().set(3, 4, 5, 5);
@ -348,7 +340,7 @@ public class Setup {
// hints // 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 = Utils.addShortcut(resources.getString(R.string.ds_hn), null, intent, dashboard, 6, 2, 1, true);
s.getCell().set(6, 2, 9, 3); s.getCell().set(6, 2, 9, 3);
sc = s.modifyShortcutConfig(); sc = s.modifyShortcutConfig();
@ -356,7 +348,7 @@ public class Setup {
sc.labelMaxLines = 7; sc.labelMaxLines = 7;
s.notifyChanged(); 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 = Utils.addShortcut(resources.getString(R.string.ds_um), null, intent, dashboard, 6, 2, 1, true);
s.getCell().set(-4, 2, -1, 3); s.getCell().set(-4, 2, -1, 3);
sc = s.modifyShortcutConfig(); sc = s.modifyShortcutConfig();
@ -365,54 +357,53 @@ public class Setup {
s.notifyChanged(); s.notifyChanged();
// start here folder // start here folder
Folder start_here; Folder start_here;
Page start_here_page; 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); start_here.getCell().set(0, 0, 1, 1);
FolderConfig fc = start_here.modifyFolderConfig(); FolderConfig fc = start_here.modifyFolderConfig();
fc.iconStyle= FolderConfig.FolderIconStyle.NORMAL; fc.iconStyle = FolderConfig.FolderIconStyle.NORMAL;
fc.titleVisibility = false; fc.titleVisibility = false;
fc.wAH = Box.AlignH.LEFT; fc.wAH = Box.AlignH.LEFT;
// fc.wAV = Box.AlignV.TOP; // fc.wAV = Box.AlignV.TOP;
fc.animationIn = FolderConfig.FolderAnimation.SLIDE_FROM_LEFT; fc.animationIn = FolderConfig.FolderAnimation.SLIDE_FROM_LEFT;
fc.animationOut = FolderConfig.FolderAnimation.SLIDE_FROM_RIGHT; fc.animationOut = FolderConfig.FolderAnimation.SLIDE_FROM_RIGHT;
fc.autoClose = true; 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); Utils.saveIconToFile(start_here.getDefaultIconFile(), icon);
start_here_page = start_here.getOrLoadFolderPage(); start_here_page = start_here.getOrLoadFolderPage();
PageConfig folder_config=start_here_page.config; PageConfig folder_config = start_here_page.config;
folder_config.defaultShortcutConfig.labelMaxLines=2; folder_config.defaultShortcutConfig.labelMaxLines = 2;
folder_config.useDesktopSize = false; folder_config.useDesktopSize = false;
// folder_config.gridPRowMode = PageConfig.SizeMode.AUTO; // folder_config.gridPRowMode = PageConfig.SizeMode.AUTO;
folder_config.gridPRowNum = 6; folder_config.gridPRowNum = 6;
folder_config.gridPColumnMode= PageConfig.SizeMode.AUTO; folder_config.gridPColumnMode = PageConfig.SizeMode.AUTO;
start_here.notifyChanged(); start_here.notifyChanged();
start_here_page.saveConfig(); start_here_page.saveConfig();
final String youtube="http://www.youtube.com/watch?v="; 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, 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, 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, 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, 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 // start here tutorials folder
Folder tutorials; Folder tutorials;
Page tutorials_page; 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); tutorials.getCell().set(0, 5, 1, 6);
start_here_page.getAndCreateIconDir(); start_here_page.getAndCreateIconDir();
icon = Utils.createIconFromText(Utils.getStandardIconSize(), "v"); icon = Utils.createIconFromText(Utils.getStandardIconSize(), "v");
Utils.saveIconToFile(tutorials.getDefaultIconFile(), icon); Utils.saveIconToFile(tutorials.getDefaultIconFile(), icon);
fc = tutorials.modifyFolderConfig(); fc = tutorials.modifyFolderConfig();
fc.iconStyle= FolderConfig.FolderIconStyle.NORMAL; fc.iconStyle = FolderConfig.FolderIconStyle.NORMAL;
fc.titleVisibility = false; fc.titleVisibility = false;
fc.wAH = Box.AlignH.LEFT; fc.wAH = Box.AlignH.LEFT;
// fc.wAV = Box.AlignV.TOP; // fc.wAV = Box.AlignV.TOP;
@ -422,14 +413,14 @@ public class Setup {
tutorials_page = tutorials.getOrLoadFolderPage(); tutorials_page = tutorials.getOrLoadFolderPage();
tutorials_page.config.useDesktopSize = false; tutorials_page.config.useDesktopSize = false;
tutorials_page.config.gridPColumnMode= PageConfig.SizeMode.AUTO; tutorials_page.config.gridPColumnMode = PageConfig.SizeMode.AUTO;
tutorials.notifyChanged(); tutorials.notifyChanged();
installShortcut(tutorials_page, 0, 0, "s", resources.getString(R.string.ds_tt), Version.WIKI_PREFIX + "tips_tricks", null); 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, 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, 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, 3, "v", resources.getString(R.string.tut_scroll), youtube + "4Kic7av9eac", null);
return all_apps_item; return all_apps_item;
} }
@ -484,7 +475,7 @@ public class Setup {
private static Item findItem(ArrayList<Item> items, String[] component_names) { private static Item findItem(ArrayList<Item> items, String[] component_names) {
// try to match package and class first, otherwise try to match the package only // try to match package and class first, otherwise try to match the package only
Item item = findItemByPackageName(items, component_names, false); Item item = findItemByPackageName(items, component_names, false);
if(item == null) { if (item == null) {
item = findItemByPackageName(items, component_names, true); 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) { private static Item findItemByPackageName(ArrayList<Item> items, String[] component_names, boolean package_only) {
for(Item i : items) { for (Item i : items) {
if(!(i instanceof Shortcut)) continue; if (!(i instanceof Shortcut)) continue;
Shortcut s=(Shortcut)i; Shortcut s = (Shortcut) i;
Intent intent=s.getIntent(); Intent intent = s.getIntent();
final ComponentName item_cn = intent.getComponent(); final ComponentName item_cn = intent.getComponent();
if(item_cn != null) { if (item_cn != null) {
final String item_pkg = item_cn.getPackageName(); final String item_pkg = item_cn.getPackageName();
for (String cn_s : component_names) { for (String cn_s : component_names) {
ComponentName cn = ComponentName.unflattenFromString(cn_s); 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) { private static Item installDockShortcut(Page dashboard, Page app_drawer, int x, int y, String[] component_names) {
Item item = findItem(app_drawer.items, 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); Shortcut shortcut = Utils.copyShortcut(item, dashboard, x, y, 1);
ItemConfig ic_dock=shortcut.modifyItemConfig(); ItemConfig ic_dock = shortcut.modifyItemConfig();
ic_dock.pinMode=ItemConfig.PinMode.XY; ic_dock.pinMode = ItemConfig.PinMode.XY;
// ic_dock.rotate=true; // ic_dock.rotate=true;
ic_dock.box.av = Box.AlignV.BOTTOM; ic_dock.box.av = Box.AlignV.BOTTOM;
ic_dock.box_s = ic_dock.box.toString(null); ic_dock.box_s = ic_dock.box.toString(null);
@ -528,7 +519,7 @@ public class Setup {
sc_dock.iconReflectionOverlap = 0; sc_dock.iconReflectionOverlap = 0;
sc_dock.iconReflectionSize = 0.7f; sc_dock.iconReflectionSize = 0.7f;
sc_dock.labelVisibility = false; sc_dock.labelVisibility = false;
shortcut.getCell().set(x, y, x+1, y+1); shortcut.getCell().set(x, y, x + 1, y + 1);
shortcut.notifyChanged(); 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) { private static void installShortcut(Page page, int x, int y, String icon_code, String label, String uri, Intent intent) {
if(intent==null) { if (intent == null) {
intent=new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
} }
Shortcut new_item=new Shortcut(page); Shortcut new_item = new Shortcut(page);
int new_id=page.findFreeItemId(); int new_id = page.findFreeItemId();
File icon_dir=page.getAndCreateIconDir(); File icon_dir = page.getAndCreateIconDir();
icon_dir.mkdirs(); 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(); int size = Utils.getStandardIconSize();
Bitmap icon = Utils.createIconFromText(size, icon_code); Bitmap icon = Utils.createIconFromText(size, icon_code);
Utils.saveIconToFile(new_item.getCustomIconFile(), icon); Utils.saveIconToFile(new_item.getCustomIconFile(), icon);
@ -562,13 +553,13 @@ public class Setup {
int color_primary_dark = resources.getColor(R.color.color_primary_dark); int color_primary_dark = resources.getColor(R.color.color_primary_dark);
Page page = engine.getOrLoadPage(Page.USER_MENU_PAGE); Page page = engine.getOrLoadPage(Page.USER_MENU_PAGE);
PageConfig page_config=page.config; PageConfig page_config = page.config;
page_config.gridPColumnNum = 5; page_config.gridPColumnNum = 5;
// page_config.gridPRowNum = 7; // page_config.gridPRowNum = 7;
page_config.gridPRowMode = PageConfig.SizeMode.AUTO; page_config.gridPRowMode = PageConfig.SizeMode.AUTO;
// page_config.gridPRowSize = (int)(large_icon_size * resources.getDisplayMetrics().scaledDensity * 1.5f); // 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(); icon_dir.mkdirs();
Folder folder = new Folder(page); Folder folder = new Folder(page);
@ -616,17 +607,23 @@ public class Setup {
Shortcut shortcut; Shortcut shortcut;
Intent intent; Intent intent;
File icon_dir=page.getAndCreateIconDir(); File icon_dir = page.getAndCreateIconDir();
id = page.findFreeItemId(); id = page.findFreeItemId();
shortcut = new Shortcut(page); shortcut = new Shortcut(page);
intent = new Intent(context, Dashboard.class); intent = new Intent(context, Dashboard.class);
intent.putExtra(LightningIntent.INTENT_EXTRA_ACTION, GlobalConfig.RUN_SCRIPT); intent.putExtra(LightningIntent.INTENT_EXTRA_ACTION, GlobalConfig.RUN_SCRIPT);
intent.putExtra(LightningIntent.INTENT_EXTRA_DATA, String.valueOf(ScriptManager.BUILTIN_USER_MENU)); 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); shortcut.setName(name);
Bitmap icon = Utils.createIconFromText(shortcut.getStdIconSize(), icon_code); Bitmap icon = Utils.createIconFromText(shortcut.getStdIconSize(), icon_code);
Utils.saveIconToFile(shortcut.getDefaultIconFile(), icon); Utils.saveIconToFile(shortcut.getDefaultIconFile(), icon);
page.addItem(shortcut); 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; package net.pierrox.lightning_launcher.views;
import net.pierrox.lightning_launcher_extreme.R;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
@ -34,298 +33,373 @@ import android.graphics.Paint.FontMetrics;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import net.pierrox.lightning_launcher_extreme.R;
public class BoxEditorView extends View implements Runnable { public class BoxEditorView extends View implements Runnable {
public interface OnBoxEditorEventListener { public static final int SEG_ML = 0;
public void onBoxSelectionChanged(Object token, int selection); 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_ML = 0; public static final int SEG_BL = 4;
public static final int SEG_MT = 1; public static final int SEG_BT = 5;
public static final int SEG_MR = 2; public static final int SEG_BR = 6;
public static final int SEG_MB = 3; public static final int SEG_BB = 7;
public static final int SEG_BL = 4; public static final int SEG_PL = 8;
public static final int SEG_BT = 5; public static final int SEG_PT = 9;
public static final int SEG_BR = 6; public static final int SEG_PR = 10;
public static final int SEG_BB = 7; public static final int SEG_PB = 11;
public static final int SEG_PL = 8; public static final int SEG_CONTENT = 12;
public static final int SEG_PT = 9; public static final int SEG_SELECTION_COLOR_MASK = 1 << SEG_BL | 1 << SEG_BT | 1 << SEG_BR | 1 << SEG_BB | 1 << SEG_CONTENT;
public static final int SEG_PR = 10; private static final int ALL_MARGINGS = 1 << SEG_ML | 1 << SEG_MT | 1 << SEG_MR | 1 << SEG_MB;
public static final int SEG_PB = 11; private static final int ALL_BORDERS = 1 << SEG_BL | 1 << SEG_BT | 1 << SEG_BR | 1 << SEG_BB;
public static final int SEG_CONTENT = 12; 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 static final int ALL_MARGINGS = 1<<SEG_ML | 1<<SEG_MT | 1<<SEG_MR | 1<<SEG_MB; private final String mMargin;
private static final int ALL_BORDERS = 1<<SEG_BL | 1<<SEG_BT | 1<<SEG_BR | 1<<SEG_BB; private final String mBorder;
private static final int ALL_PADDINGS = 1<<SEG_PL | 1<<SEG_PT | 1<<SEG_PR | 1<<SEG_PB; private final String mPadding;
private final String mContent;
public static final int SEG_SELECTION_COLOR_MASK = 1<<SEG_BL | 1<<SEG_BT | 1<<SEG_BR | 1<<SEG_BB | 1<<SEG_CONTENT; private final String mLeft;
private final String mTop;
private static final int DIVIDER=8; private final String mRight;
private final String mBottom;
private String mMargin, mBorder, mPadding, mContent, mLeft, mTop, mRight, mBottom; private final Paint mCountourPlainPaint;
private final Paint mCountourDashPaint;
private Paint mCountourPlainPaint; private final Paint mBorderAreaPaint;
private Paint mCountourDashPaint; private final Paint mSelectedAreaPaint;
private Paint mBorderAreaPaint; private final Paint mTextPaint;
private Paint mSelectedAreaPaint; private final RectF mOuterRect = new RectF();
private Paint mTextPaint; private final RectF mMarginRect = new RectF();
private FontMetrics mTextMetrics; private final RectF mBorderRect = new RectF();
private final RectF mPaddingRect = new RectF();
private RectF mOuterRect = new RectF(); private final Path[] mAreas = new Path[13];
private RectF mMarginRect = new RectF(); private FontMetrics mTextMetrics;
private RectF mBorderRect = new RectF(); private int mSelectedSegments;
private RectF mPaddingRect = new RectF();
private Path[] mAreas = new Path[13];
private int mSelectedSegments;
private int mTouchedSegment; private int mTouchedSegment;
private Object mOnBoxEditorEventToken;
private Object mOnBoxEditorEventToken; private OnBoxEditorEventListener mOnBoxEditorEventListener;
private OnBoxEditorEventListener mOnBoxEditorEventListener; private boolean mHasLongClicked;
private boolean mHasLongClicked; public BoxEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
public BoxEditorView(Context context, AttributeSet attrs) {
super(context, attrs); mMargin = context.getString(R.string.margin);
mBorder = context.getString(R.string.border);
mMargin=context.getString(R.string.margin); mPadding = context.getString(R.string.padding);
mBorder=context.getString(R.string.border); mContent = context.getString(R.string.content);
mPadding=context.getString(R.string.padding); mLeft = context.getString(R.string.left);
mContent=context.getString(R.string.content); mTop = context.getString(R.string.top);
mLeft=context.getString(R.string.left); mRight = context.getString(R.string.right);
mTop=context.getString(R.string.top); mBottom = context.getString(R.string.bottom);
mRight=context.getString(R.string.right);
mBottom=context.getString(R.string.bottom); mCountourPlainPaint = new Paint();
mCountourPlainPaint.setStyle(Paint.Style.STROKE);
mCountourPlainPaint = new Paint(); mCountourPlainPaint.setColor(Color.BLACK);
mCountourPlainPaint.setStyle(Paint.Style.STROKE);
mCountourPlainPaint.setColor(Color.BLACK); mCountourDashPaint = new Paint();
mCountourDashPaint.setStyle(Paint.Style.STROKE);
mCountourDashPaint = new Paint(); mCountourDashPaint.setColor(Color.BLACK);
mCountourDashPaint.setStyle(Paint.Style.STROKE); mCountourDashPaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0));
mCountourDashPaint.setColor(Color.BLACK);
mCountourDashPaint.setPathEffect(new DashPathEffect(new float[] { 5, 5 }, 0)); mBorderAreaPaint = new Paint();
mBorderAreaPaint.setStyle(Paint.Style.FILL);
mBorderAreaPaint = new Paint(); mBorderAreaPaint.setColor(0xffb0b0b0);
mBorderAreaPaint.setStyle(Paint.Style.FILL);
mBorderAreaPaint.setColor(0xffb0b0b0); mSelectedAreaPaint = new Paint();
mSelectedAreaPaint.setStyle(Paint.Style.FILL);
mSelectedAreaPaint = new Paint();
mSelectedAreaPaint.setStyle(Paint.Style.FILL);
mSelectedAreaPaint.setColor(0x808080ff); // workaround for a drawing bug on some devices mSelectedAreaPaint.setColor(0x808080ff); // workaround for a drawing bug on some devices
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.BLACK); mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextAlign(Paint.Align.CENTER); mTextPaint.setTextAlign(Paint.Align.CENTER);
} }
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec); int w = MeasureSpec.getSize(widthMeasureSpec);
int max = getResources().getDimensionPixelSize(R.dimen.max_box_editor_width); int max = getResources().getDimensionPixelSize(R.dimen.max_box_editor_width);
if(w>max) w=max; if (w > max) w = max;
setMeasuredDimension(w, w*2/3); 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 int ol = sw / 2;
protected void onSizeChanged(int w, int h, int oldw, int oldh) { int ot = sh / 2;
final int sw=(w<h ? w : h)/DIVIDER; int or = w - sw / 2;
final int sh=sw; int ob = h - sh / 2;
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;
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; int ml = ol + sw;
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; int mt = ot + sh;
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; int mr = or - sw;
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; int mb = ob - sh;
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 int bl = ml + sw;
protected void onDraw(Canvas canvas) { int bt = mt + sh;
final int w = getWidth(); int br = mr - sw;
final int h = getHeight(); int bb = mb - sh;
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 int pl = bl + sw;
public boolean onTouchEvent(MotionEvent event) { int pt = bt + sh;
int action = event.getAction(); int pr = br - sw;
switch(action) { int pb = bb - sh;
case MotionEvent.ACTION_DOWN:
mHasLongClicked = false;
postDelayed(this, ViewConfiguration.getLongPressTimeout());
mTouchedSegment = -1; mOuterRect.set(ol, ot, or, ob);
Region r = new Region(); mMarginRect.set(ml, mt, mr, mb);
Region clip = new Region(0, 0, getWidth(), getHeight()); mBorderRect.set(bl, bt, br, bb);
for(int i=0; i<mAreas.length; i++) { mPaddingRect.set(pl, pt, pr, pb);
Path p = mAreas[i];
r.setPath(p, clip); Path p;
if(r.contains((int)event.getX(), (int)event.getY())) {
mTouchedSegment = i; p = new Path();
break; 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;
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_UP: if (!mHasLongClicked) {
if(!mHasLongClicked) { removeCallbacks(this);
removeCallbacks(this);
if (mTouchedSegment != -1) {
if(mTouchedSegment != -1) { mSelectedSegments ^= (1 << mTouchedSegment);
mSelectedSegments ^= (1<<mTouchedSegment); invalidate();
invalidate(); mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments);
mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments); }
} }
} return true;
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_CANCEL: removeCallbacks(this);
removeCallbacks(this); return true;
return true; }
}
return super.onTouchEvent(event);
return super.onTouchEvent(event); }
}
@Override
@Override public void run() {
public void run() { mHasLongClicked = true;
mHasLongClicked = true; if (mTouchedSegment >= SEG_ML && mTouchedSegment <= SEG_MB) {
if(mTouchedSegment >= SEG_ML && mTouchedSegment <= SEG_MB) { if ((mSelectedSegments & ALL_MARGINGS) == ALL_MARGINGS) {
if((mSelectedSegments & ALL_MARGINGS) == ALL_MARGINGS) {
mSelectedSegments &= ~ALL_MARGINGS; mSelectedSegments &= ~ALL_MARGINGS;
} else { } else {
mSelectedSegments |= ALL_MARGINGS; mSelectedSegments |= ALL_MARGINGS;
} }
} else if(mTouchedSegment >= SEG_BL && mTouchedSegment <= SEG_BB) { } else if (mTouchedSegment >= SEG_BL && mTouchedSegment <= SEG_BB) {
if((mSelectedSegments & ALL_BORDERS) == ALL_BORDERS) { if ((mSelectedSegments & ALL_BORDERS) == ALL_BORDERS) {
mSelectedSegments &= ~ALL_BORDERS; mSelectedSegments &= ~ALL_BORDERS;
} else { } else {
mSelectedSegments |= ALL_BORDERS; mSelectedSegments |= ALL_BORDERS;
} }
} else if(mTouchedSegment >= SEG_PL && mTouchedSegment <= SEG_PB) { } else if (mTouchedSegment >= SEG_PL && mTouchedSegment <= SEG_PB) {
if((mSelectedSegments & ALL_PADDINGS) == ALL_PADDINGS) { if ((mSelectedSegments & ALL_PADDINGS) == ALL_PADDINGS) {
mSelectedSegments &= ~ALL_PADDINGS; mSelectedSegments &= ~ALL_PADDINGS;
} else { } else {
mSelectedSegments |= ALL_PADDINGS; mSelectedSegments |= ALL_PADDINGS;
} }
} else { } else {
if(mSelectedSegments != 0) { if (mSelectedSegments != 0) {
mSelectedSegments = 0; mSelectedSegments = 0;
} else { } else {
mSelectedSegments = 0xffffffff; mSelectedSegments = 0xffffffff;
} }
} }
mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments); mOnBoxEditorEventListener.onBoxSelectionChanged(mOnBoxEditorEventToken, mSelectedSegments);
invalidate(); invalidate();
} }
public void setOnBoxEditorEventListener(Object token, OnBoxEditorEventListener listener) {
mOnBoxEditorEventToken = token;
mOnBoxEditorEventListener = listener;
}
private void drawArea(Canvas canvas, int n) { public void setOnBoxEditorEventListener(Object token, OnBoxEditorEventListener listener) {
Path p = mAreas[n]; mOnBoxEditorEventToken = token;
if(p != null) { mOnBoxEditorEventListener = listener;
if((mSelectedSegments & 1<<n)!=0) { }
canvas.drawPath(p, mSelectedAreaPaint);
} 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") @SuppressWarnings("deprecation")
public class BubbleLayout extends AbsoluteLayout { public class BubbleLayout extends AbsoluteLayout {
private float mDensity; private final int mBubbleArrowShift;
private float mDensity;
private int mScreenPadding; private int mScreenPadding;
private Rect mItemBounds; private Rect mItemBounds;
private int mBubbleArrowShift;
public BubbleLayout(Context context, AttributeSet attrs) {
public BubbleLayout(Context context, AttributeSet attrs) { super(context, attrs);
super(context, attrs);
mBubbleArrowShift = getContext().getResources().getDimensionPixelSize(R.dimen.bubble_arrow_shift); mBubbleArrowShift = getContext().getResources().getDimensionPixelSize(R.dimen.bubble_arrow_shift);
} }
public void setScreenPadding(int padding) { public void setScreenPadding(int padding) {
mScreenPadding = padding; mScreenPadding = padding;
} }
public void setItemBounds(Rect item_bounds) {
mItemBounds = new Rect(item_bounds);
mItemBounds.offset(0, -mScreenPadding);
requestLayout();
}
@Override public void setItemBounds(Rect item_bounds) {
protected void onLayout(boolean changed, int l, int t, int r, int b) { mItemBounds = new Rect(item_bounds);
if(mItemBounds == null) { mItemBounds.offset(0, -mScreenPadding);
return; requestLayout();
} }
View bubble = getChildAt(0); @Override
View arrow_down = getChildAt(1); protected void onLayout(boolean changed, int l, int t, int r, int b) {
View arrow_up = getChildAt(2); if (mItemBounds == null) {
return;
final int w = getWidth(); }
final int h = getHeight();
View bubble = getChildAt(0);
boolean above = (h-mItemBounds.bottom) < mItemBounds.top; View arrow_down = getChildAt(1);
View arrow_up = getChildAt(2);
View arrow;
if(above) { final int w = getWidth();
arrow = arrow_down; final int h = getHeight();
arrow_up.layout(-1, -1, -1, -1);
} else { boolean above = (h - mItemBounds.bottom) < mItemBounds.top;
arrow = arrow_up;
arrow_down.layout(-1, -1, -1, -1); View arrow;
} if (above) {
arrow = arrow_down;
int b_left, b_right, b_top, b_bottom; arrow_up.layout(-1, -1, -1, -1);
int a_left, a_right, a_top, a_bottom; } else {
arrow = arrow_up;
arrow_down.layout(-1, -1, -1, -1);
}
final int bw = bubble.getMeasuredWidth();
final int bh = bubble.getMeasuredHeight(); int b_left, b_right, b_top, b_bottom;
int a_left, a_right, a_top, a_bottom;
final int aw = arrow.getMeasuredWidth();
final int ah = arrow.getMeasuredHeight();
final int bw = bubble.getMeasuredWidth();
final int i_center = mItemBounds.centerX(); final int bh = bubble.getMeasuredHeight();
b_left = i_center - bw/2; final int aw = arrow.getMeasuredWidth();
if(b_left<0) b_left=0; final int ah = arrow.getMeasuredHeight();
b_right = b_left+bw;
if(b_right>w) { final int i_center = mItemBounds.centerX();
b_left = w-bw;
b_right = w; b_left = i_center - bw / 2;
} if (b_left < 0) b_left = 0;
b_right = b_left + bw;
a_left = i_center - aw/2; if (b_right > w) {
if(a_left<0) a_left = 0; b_left = w - bw;
a_right = a_left + aw; b_right = w;
if(a_right > w) { }
a_left = w - aw;
a_right = w; a_left = i_center - aw / 2;
} if (a_left < 0) a_left = 0;
a_right = a_left + aw;
int shift=Math.round(mDensity*mBubbleArrowShift/1.5f)-1; if (a_right > w) {
a_left = w - aw;
a_right = w;
}
int shift = Math.round(mDensity * mBubbleArrowShift / 1.5f) - 1;
int anchor_y; int anchor_y;
// int max_height_delta = h/3; // int max_height_delta = h/3;
@ -116,7 +115,7 @@ public class BubbleLayout extends AbsoluteLayout {
// anchor_y =above ? mItemBounds.top : mItemBounds.bottom; // anchor_y =above ? mItemBounds.top : mItemBounds.bottom;
// } else { // } else {
int delta; int delta;
if(mItemBounds.height()==0) { if (mItemBounds.height() == 0) {
delta = 0; delta = 0;
} else { } else {
int mh = mItemBounds.height() / 2; int mh = mItemBounds.height() / 2;
@ -125,32 +124,32 @@ public class BubbleLayout extends AbsoluteLayout {
anchor_y = mItemBounds.centerY() + (above ? -delta : delta); anchor_y = mItemBounds.centerY() + (above ? -delta : delta);
// } // }
if(above) { if (above) {
// above // above
b_bottom = anchor_y - ah + shift; b_bottom = anchor_y - ah + shift;
b_top = b_bottom - bh; b_top = b_bottom - bh;
a_bottom = anchor_y; a_bottom = anchor_y;
a_top = a_bottom - ah; a_top = a_bottom - ah;
} else { } else {
// below // below
b_top = anchor_y + ah - shift; b_top = anchor_y + ah - shift;
b_bottom = b_top + bh; b_bottom = b_top + bh;
a_top = anchor_y; a_top = anchor_y;
a_bottom = a_top + ah; a_bottom = a_top + ah;
} }
if(b_top<0) { if (b_top < 0) {
b_top=above ? 0 : ah; b_top = above ? 0 : ah;
int height_diff=bh-(b_bottom-b_top); int height_diff = bh - (b_bottom - b_top);
if(height_diff>0) { if (height_diff > 0) {
b_bottom+=height_diff; b_bottom += height_diff;
a_top+=height_diff; a_top += height_diff;
a_bottom+=height_diff; a_bottom += height_diff;
} }
if(above) { if (above) {
int max_height = anchor_y;//h/2-ah; int max_height = anchor_y;//h/2-ah;
int height = b_bottom - b_top; int height = b_bottom - b_top;
if (height > max_height) { if (height > max_height) {
@ -160,14 +159,14 @@ public class BubbleLayout extends AbsoluteLayout {
a_bottom += height_diff; a_bottom += height_diff;
} }
} }
} }
if(b_bottom>h) b_bottom=h; 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);
}
public void setDensity(float density) { bubble.layout(b_left, b_top, b_right, b_bottom);
mDensity = density; 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; import net.pierrox.lightning_launcher_extreme.R;
public class CropperView extends ImageView { public class CropperView extends ImageView {
public interface OnCropperViewEvent { private final Paint mSelectionRectPaint;
public void onCropperViewSelectionChanged(Rect selection); private final Paint mOutHighlightPaint;
public void onCropperViewClick(); 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 Bitmap mBitmap;
private Rect mSelectionRect; 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 boolean mIsDown;
private int mDownX, mDownY; private int mDownX, mDownY;
private int mCurrentMoveArea; private int mCurrentMoveArea;
private Rect mInitialSelectionRect; private Rect mInitialSelectionRect;
private long mLastClickDate; private long mLastClickDate;
private boolean mMoving; private boolean mMoving;
private OnCropperViewEvent mListener; private OnCropperViewEvent mListener;
private final Runnable mClickRunnable = new Runnable() {
private Runnable mClickRunnable = new Runnable() {
@Override @Override
public void run() { 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); mSelectionRectPaint.setStyle(Paint.Style.STROKE);
mDensity = resources.getDisplayMetrics().density; mDensity = resources.getDisplayMetrics().density;
mHandleTouchSize = (int)(16*mDensity); mHandleTouchSize = (int) (16 * mDensity);
mTouchSlope = ViewConfiguration.get(context).getScaledTouchSlop(); 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) { protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, 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 src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h); RectF dst = new RectF(0, 0, w, h);
Matrix m = new Matrix(); Matrix m = new Matrix();
@ -140,8 +134,8 @@ public class CropperView extends ImageView {
final int handleHHeight = mHandleHeightBitmap.getHeight(); final int handleHHeight = mHandleHeightBitmap.getHeight();
canvas.drawBitmap(mHandleWidthBitmap, mSelectionRect.left - handleWWidth / 2, mSelectionRect.centerY() - handleWHeight / 2, null); 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(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.top - handleHHeight / 2, null);
canvas.drawBitmap(mHandleHeightBitmap, centerX - handleHWidth /2, mSelectionRect.bottom- handleHHeight /2, null); canvas.drawBitmap(mHandleHeightBitmap, centerX - handleHWidth / 2, mSelectionRect.bottom - handleHHeight / 2, null);
} }
@Override @Override
@ -155,7 +149,7 @@ public class CropperView extends ImageView {
final int width = getWidth(); final int width = getWidth();
final int height = getHeight(); final int height = getHeight();
switch(event.getAction()) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
removeCallbacks(mClickRunnable); removeCallbacks(mClickRunnable);
mIsDown = true; mIsDown = true;
@ -164,15 +158,15 @@ public class CropperView extends ImageView {
mDownY = y; mDownY = y;
mCurrentMoveArea = Gravity.NO_GRAVITY; 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; 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; mCurrentMoveArea = Gravity.BOTTOM;
} else if (Math.abs(mDownX - mSelectionRect.left) < mHandleTouchSize && mDownY > mSelectionRect.top && mDownY < mSelectionRect.bottom) { } else if (Math.abs(mDownX - mSelectionRect.left) < mHandleTouchSize && mDownY > mSelectionRect.top && mDownY < mSelectionRect.bottom) {
mCurrentMoveArea = Gravity.LEFT; 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; mCurrentMoveArea = Gravity.RIGHT;
} else if(mSelectionRect.contains(mDownX, mDownY)) { } else if (mSelectionRect.contains(mDownX, mDownY)) {
mCurrentMoveArea = Gravity.CENTER; mCurrentMoveArea = Gravity.CENTER;
} }
mInitialSelectionRect = new Rect(mSelectionRect); mInitialSelectionRect = new Rect(mSelectionRect);
@ -231,7 +225,7 @@ public class CropperView extends ImageView {
return true; return true;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
if(mIsDown) { if (mIsDown) {
mIsDown = false; mIsDown = false;
removeCallbacks(mClickRunnable); removeCallbacks(mClickRunnable);
if (!mMoving) { if (!mMoving) {
@ -278,37 +272,13 @@ public class CropperView extends ImageView {
mListener = listener; 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() { public Rect getSelection() {
mTmpRectF.set(mSelectionRect); mTmpRectF.set(mSelectionRect);
getImageMatrix().invert(mTmpMatrix); getImageMatrix().invert(mTmpMatrix);
Drawable drawable = getDrawable(); Drawable drawable = getDrawable();
Bitmap image = ((BitmapDrawable) drawable).getBitmap(); Bitmap image = ((BitmapDrawable) drawable).getBitmap();
float sx = image.getWidth() / (float)drawable.getIntrinsicWidth(); float sx = image.getWidth() / (float) drawable.getIntrinsicWidth();
float sy = image.getHeight() / (float)drawable.getIntrinsicHeight(); float sy = image.getHeight() / (float) drawable.getIntrinsicHeight();
mTmpMatrix.postScale(sx, sy); mTmpMatrix.postScale(sx, sy);
mTmpMatrix.mapRect(mTmpRectF); mTmpMatrix.mapRect(mTmpRectF);
mTmpRectF.round(mTmpRect); mTmpRectF.round(mTmpRect);
@ -316,9 +286,33 @@ public class CropperView extends ImageView {
return mTmpRect; 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() { private void sendSelectionChangedEvent() {
if(mListener != null) { if (mListener != null) {
mListener.onCropperViewSelectionChanged(getSelection()); 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; import net.pierrox.lightning_launcher_extreme.R;
public class EditBarHiderView extends ImageButton implements Runnable { 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 float mAngle;
private Matrix mMatrix; private Matrix mMatrix;
private long mAnimStart; private long mAnimStart;
@ -64,15 +64,15 @@ public class EditBarHiderView extends ImageButton implements Runnable {
@Override @Override
public void run() { public void run() {
long delta = AnimationUtils.currentAnimationTimeMillis() - mAnimStart; long delta = AnimationUtils.currentAnimationTimeMillis() - mAnimStart;
if(delta> ANIM_DURATION) { if (delta > ANIM_DURATION) {
delta = ANIM_DURATION; delta = ANIM_DURATION;
} }
float angle = 180f*delta / ANIM_DURATION; float angle = 180f * delta / ANIM_DURATION;
if(!mAnimDirection) { if (!mAnimDirection) {
angle = 180 - angle; angle = 180 - angle;
} }
setEditBarHiderRotation(angle); setEditBarHiderRotation(angle);
if(delta == ANIM_DURATION) { if (delta == ANIM_DURATION) {
mMatrix = null; mMatrix = null;
} else { } else {
post(this); post(this);
@ -87,7 +87,7 @@ public class EditBarHiderView extends ImageButton implements Runnable {
private void updateMatrix() { private void updateMatrix() {
int dw = mBitmap.getWidth() / 2; int dw = mBitmap.getWidth() / 2;
int dh = mBitmap.getHeight() / 2; int dh = mBitmap.getHeight() / 2;
if(mMatrix == null) { if (mMatrix == null) {
mMatrix = new Matrix(); mMatrix = new Matrix();
} else { } else {
mMatrix.reset(); mMatrix.reset();
@ -99,7 +99,7 @@ public class EditBarHiderView extends ImageButton implements Runnable {
} }
public void setArrowDirection(boolean open) { public void setArrowDirection(boolean open) {
if(mAnimDirection != open) { if (mAnimDirection != open) {
mAnimDirection = open; mAnimDirection = open;
removeCallbacks(this); removeCallbacks(this);
mAnimStart = AnimationUtils.currentAnimationTimeMillis(); mAnimStart = AnimationUtils.currentAnimationTimeMillis();

View file

@ -30,38 +30,37 @@ import android.view.KeyEvent;
import android.widget.EditText; import android.widget.EditText;
public class EditTextIme extends EditText { public class EditTextIme extends EditText {
private OnEditTextImeListener mListener; 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 boolean mHadKeyDown; private boolean mHadKeyDown;
@Override public EditTextIme(Context context, AttributeSet attrs) {
public boolean onKeyPreIme (int keyCode, KeyEvent event) { super(context, attrs);
if(keyCode==KeyEvent.KEYCODE_BACK) { }
switch(event.getAction()) {
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: case KeyEvent.ACTION_DOWN:
mHadKeyDown = true; mHadKeyDown = true;
return false; return false;
case KeyEvent.ACTION_UP: case KeyEvent.ACTION_UP:
if(mHadKeyDown && mListener != null) { if (mHadKeyDown && mListener != null) {
mListener.onEditTextImeBackPressed(); mListener.onEditTextImeBackPressed();
} }
mHadKeyDown = false; mHadKeyDown = false;
return true; 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 class HierarchyScreen {
public interface HierarchyScreenListener { private final LightningEngine mLightningEngine;
void onHierarchyScreenItemEdit(ContainerPath path, Item item); private final Screen mScreen;
void onHierarchyScreenContainerSettings(ContainerPath path); private final HierarchyScreenListener mListener;
void onHierarchyScreenItemMoved(HierarchyItem which, HierarchyItem before, HierarchyItem after);
int[] onHierarchyScreenGetRootPages();
}
private LightningEngine mLightningEngine;
private Screen mScreen;
private View mRootView; private View mRootView;
private HierarchyScreenListener mListener;
private Animation mHierarchyPaneAnimIn; private Animation mHierarchyPaneAnimIn;
private Animation mHierarchyPaneAnimOut; private Animation mHierarchyPaneAnimOut;
private DragSortListView mDragSortListView; private DragSortListView mDragSortListView;
private HierarchyAdapter mAdapter; private HierarchyAdapter mAdapter;
public HierarchyScreen(LightningEngine engine, Screen screen, HierarchyScreenListener listener) { public HierarchyScreen(LightningEngine engine, Screen screen, HierarchyScreenListener listener) {
mLightningEngine = engine; mLightningEngine = engine;
mScreen = screen; mScreen = screen;
@ -84,7 +75,7 @@ public class HierarchyScreen {
} }
public void destroy() { public void destroy() {
if(mAdapter != null) { if (mAdapter != null) {
mAdapter.destroy(); mAdapter.destroy();
} }
} }
@ -94,15 +85,15 @@ public class HierarchyScreen {
} }
public void show(ContainerPath scrollToPath) { public void show(ContainerPath scrollToPath) {
if(mRootView == null) { if (mRootView == null) {
// setup // setup
final Context context = mScreen.getContext(); final Context context = mScreen.getContext();
mRootView = LayoutInflater.from(context).inflate(R.layout.hierarchy_pane, null); mRootView = LayoutInflater.from(context).inflate(R.layout.hierarchy_pane, null);
ViewGroup contentView = mScreen.getContentView(); 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 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); mAdapter = new HierarchyAdapter(context, mDragSortListView);
mHierarchyPaneAnimIn = AnimationUtils.makeInAnimation(context, true); mHierarchyPaneAnimIn = AnimationUtils.makeInAnimation(context, true);
@ -123,9 +114,9 @@ public class HierarchyScreen {
HierarchyItem which = mAdapter.getItem(from); HierarchyItem which = mAdapter.getItem(from);
if (from == to) { if (from == to) {
String name; String name;
if(which.isContainer()) { if (which.isContainer()) {
Page page = mLightningEngine.getOrLoadPage(which.page); 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 { } else {
name = Utils.formatItemName(which.item, 0, 0); name = Utils.formatItemName(which.item, 0, 0);
} }
@ -153,7 +144,6 @@ public class HierarchyScreen {
}); });
mDragSortListView.setDragListener(new DragSortListView.DragListener() { mDragSortListView.setDragListener(new DragSortListView.DragListener() {
@Override @Override
public void drag(int from, int to) { public void drag(int from, int to) {
@ -178,14 +168,14 @@ public class HierarchyScreen {
}); });
} }
if(!isShown()) { if (!isShown()) {
if(scrollToPath != null) { if (scrollToPath != null) {
expandPath(scrollToPath); expandPath(scrollToPath);
} }
refresh(); refresh();
if(scrollToPath != null) { if (scrollToPath != null) {
int pos = 0; int pos = 0;
for (HierarchyItem hi : mAdapter.mItems) { for (HierarchyItem hi : mAdapter.mItems) {
if (hi.isContainer() && hi.path.equals(scrollToPath)) { if (hi.isContainer() && hi.path.equals(scrollToPath)) {
@ -203,14 +193,14 @@ public class HierarchyScreen {
private void expandPath(ContainerPath path) { private void expandPath(ContainerPath path) {
ContainerPath parent = path.getParent(); ContainerPath parent = path.getParent();
if(parent != null) { if (parent != null) {
expandPath(parent); expandPath(parent);
} }
mAdapter.setExpandedState(path, true); mAdapter.setExpandedState(path, true);
} }
public void hide() { public void hide() {
if(isShown()) { if (isShown()) {
mRootView.setVisibility(View.GONE); mRootView.setVisibility(View.GONE);
mRootView.startAnimation(mHierarchyPaneAnimOut); mRootView.startAnimation(mHierarchyPaneAnimOut);
} }
@ -225,9 +215,18 @@ public class HierarchyScreen {
mAdapter.notifyDataSetChanged(); 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 static class ExpandedPathSet {
private HashSet<String> mExpandedPaths = new HashSet<>(); private final HashSet<String> mExpandedPaths = new HashSet<>();
public boolean add(ContainerPath path) { public boolean add(ContainerPath path) {
return mExpandedPaths.add(path.toString()); 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) { public HierarchyPath(HierarchyItem item) {
super((String)null); super((String) null);
StringBuilder path = new StringBuilder(); StringBuilder path = new StringBuilder();
build(item, path); build(item, path);
mPath = path.toString(); mPath = path.toString();
} }
private void build(HierarchyItem item, StringBuilder out) { private void build(HierarchyItem item, StringBuilder out) {
if(item.parent != null) { if (item.parent != null) {
build(item.parent, out); build(item.parent, out);
out.append('/'); out.append('/');
} }
if(item.item == null) { if (item.item == null) {
out.append(item.page); out.append(item.page);
} else { } else {
out.append(item.item.getId()); out.append(item.item.getId());
@ -276,6 +275,7 @@ public class HierarchyScreen {
this.page = page; this.page = page;
this.path = new HierarchyPath(this); this.path = new HierarchyPath(this);
} }
public HierarchyItem(HierarchyItem parent, int level, int page, Item item) { public HierarchyItem(HierarchyItem parent, int level, int page, Item item) {
this.parent = parent; this.parent = parent;
this.level = level; this.level = level;
@ -283,20 +283,21 @@ public class HierarchyScreen {
this.item = item; this.item = item;
this.path = new HierarchyPath(this); this.path = new HierarchyPath(this);
} }
public boolean isContainer() { public boolean isContainer() {
return item == null || item instanceof Folder; return item == null || item instanceof Folder;
} }
public int getContainerId() { public int getContainerId() {
if(item == null) { if (item == null) {
return page; return page;
} else { } else {
return ((Folder)item).getFolderPageId(); return ((Folder) item).getFolderPageId();
} }
} }
public int getParentContainerId() { public int getParentContainerId() {
if(item == null) { if (item == null) {
return Page.NONE; return Page.NONE;
} else { } else {
return Utils.getPageForItem(item); return Utils.getPageForItem(item);
@ -305,16 +306,22 @@ public class HierarchyScreen {
} }
private class HierarchyAdapter extends BaseAdapter implements View.OnClickListener, View.OnLongClickListener { private class HierarchyAdapter extends BaseAdapter implements View.OnClickListener, View.OnLongClickListener {
private Context mContext; private final Context mContext;
private ListView mHostListView; private final ListView mHostListView;
private LightningEngine.PageManager mPageManager; 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 ArrayList<HierarchyItem> mItems;
private ExpandedPathSet mExpandedPaths;
private int mIndent;
private int mHoveredItem = -1; private int mHoveredItem = -1;
public HierarchyAdapter(Context context, ListView hostListView) { public HierarchyAdapter(Context context, ListView hostListView) {
@ -362,16 +369,16 @@ public class HierarchyScreen {
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { 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); 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.setTypeface(LLApp.get().getIconsTypeface());
containerSettingsButton.setOnClickListener(this); containerSettingsButton.setOnClickListener(this);
containerSettingsButton.setOnLongClickListener(this); containerSettingsButton.setOnLongClickListener(this);
containerSettingsButton.setContentDescription(mContext.getString(R.string.mi_es_settings)); 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.setTypeface(LLApp.get().getIconsTypeface());
editButton.setOnClickListener(this); editButton.setOnClickListener(this);
editButton.setOnLongClickListener(this); editButton.setOnLongClickListener(this);
@ -379,15 +386,15 @@ public class HierarchyScreen {
} }
HierarchyItem hi = getItem(position); 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); Page page = mLightningEngine.getOrLoadPage(hi.page);
CharSequence label; CharSequence label;
if(hi.item == null) { if (hi.item == null) {
label = Utils.formatPageName(page, hi.parent==null ? null : hi.parent.item); label = Utils.formatPageName(page, hi.parent == null ? null : hi.parent.item);
} else { } else {
label = Utils.formatItemName(hi.item, 0, 0); label = Utils.formatItemName(hi.item, 0, 0);
} }
if(hi.isContainer()) { if (hi.isContainer()) {
SpannableString spannedLabel = new SpannableString(label); SpannableString spannedLabel = new SpannableString(label);
spannedLabel.setSpan(new StyleSpan(Typeface.BOLD), 0, label.length(), 0); spannedLabel.setSpan(new StyleSpan(Typeface.BOLD), 0, label.length(), 0);
label = spannedLabel; label = spannedLabel;
@ -395,18 +402,18 @@ public class HierarchyScreen {
textView.setText(label); textView.setText(label);
textView.setPadding(hi.level * mIndent, 0, 0, 0); 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.setTag(hi);
containerSettingsButton.setVisibility(hi.isContainer() ? View.VISIBLE : View.INVISIBLE); 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); editButton.setTag(hi);
return convertView; return convertView;
} }
public void setExpandedState(ContainerPath item, boolean expanded) { public void setExpandedState(ContainerPath item, boolean expanded) {
if(expanded) { if (expanded) {
mExpandedPaths.add(item); mExpandedPaths.add(item);
} else { } else {
mExpandedPaths.remove(item); mExpandedPaths.remove(item);
@ -414,7 +421,7 @@ public class HierarchyScreen {
} }
public void toggleExpandedState(ContainerPath path) { public void toggleExpandedState(ContainerPath path) {
if(mExpandedPaths.contains(path)) { if (mExpandedPaths.contains(path)) {
mExpandedPaths.remove(path); mExpandedPaths.remove(path);
} else { } else {
mExpandedPaths.add(path); mExpandedPaths.add(path);
@ -423,12 +430,16 @@ public class HierarchyScreen {
notifyDataSetChanged(); notifyDataSetChanged();
} }
public int getHoveredItem() {
return mHoveredItem;
}
public void setHoveredItem(int position) { public void setHoveredItem(int position) {
if (mHoveredItem != position) { if (mHoveredItem != position) {
if(mHoveredItem != -1) { if (mHoveredItem != -1) {
setItemHoveredState(mHoveredItem, false); setItemHoveredState(mHoveredItem, false);
} }
if(position != -1 && getItem(position).isContainer()) { if (position != -1 && getItem(position).isContainer()) {
mHoveredItem = position; mHoveredItem = position;
setItemHoveredState(mHoveredItem, true); setItemHoveredState(mHoveredItem, true);
} else { } else {
@ -437,10 +448,6 @@ public class HierarchyScreen {
} }
} }
public int getHoveredItem() {
return mHoveredItem;
}
private void setItemHoveredState(int position, boolean hovered) { private void setItemHoveredState(int position, boolean hovered) {
View view = mHostListView.getChildAt(position - mHostListView.getFirstVisiblePosition()); View view = mHostListView.getChildAt(position - mHostListView.getFirstVisiblePosition());
if (view != null) { if (view != null) {
@ -453,7 +460,7 @@ public class HierarchyScreen {
mItems = new ArrayList<>(); mItems = new ArrayList<>();
int[] pages = mListener.onHierarchyScreenGetRootPages(); int[] pages = mListener.onHierarchyScreenGetRootPages();
for(int page : pages) { for (int page : pages) {
HierarchyItem desktopHierarchyItem = new HierarchyItem(null, 0, page); HierarchyItem desktopHierarchyItem = new HierarchyItem(null, 0, page);
mItems.add(desktopHierarchyItem); mItems.add(desktopHierarchyItem);
addPageItems(desktopHierarchyItem, page, 1); addPageItems(desktopHierarchyItem, page, 1);
@ -461,7 +468,7 @@ public class HierarchyScreen {
} }
private void addPageItems(HierarchyItem parent, int page, int level) { private void addPageItems(HierarchyItem parent, int page, int level) {
if(!mExpandedPaths.contains(parent.path)) { if (!mExpandedPaths.contains(parent.path)) {
return; return;
} }
@ -469,7 +476,7 @@ public class HierarchyScreen {
for (Item item : p.items) { for (Item item : p.items) {
HierarchyItem hierarchyItem = new HierarchyItem(parent, level, page, item); HierarchyItem hierarchyItem = new HierarchyItem(parent, level, page, item);
mItems.add(hierarchyItem); mItems.add(hierarchyItem);
if(item instanceof Folder) { if (item instanceof Folder) {
Folder folder = (Folder) item; Folder folder = (Folder) item;
addPageItems(hierarchyItem, folder.getFolderPageId(), level + 1); addPageItems(hierarchyItem, folder.getFolderPageId(), level + 1);
} }
@ -480,8 +487,12 @@ public class HierarchyScreen {
public void onClick(View v) { public void onClick(View v) {
HierarchyItem hi = (HierarchyItem) v.getTag(); HierarchyItem hi = (HierarchyItem) v.getTag();
switch (v.getId()) { switch (v.getId()) {
case R.id.eb_edit: mListener.onHierarchyScreenItemEdit(hi.path, hi.item); break; case R.id.eb_edit:
case R.id.eb_cs: mListener.onHierarchyScreenContainerSettings(new HierarchyPath(hi)); break; 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) { public boolean onLongClick(View v) {
int label_res = 0; int label_res = 0;
switch (v.getId()) { switch (v.getId()) {
case R.id.eb_edit: label_res = R.string.hs_ed; break; case R.id.eb_edit:
case R.id.eb_cs: label_res = R.string.mi_es_settings; break; 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]; int[] location = new int[2];
v.getLocationOnScreen(location); v.getLocationOnScreen(location);
Toast toast = Toast.makeText(mContext, label_res, Toast.LENGTH_SHORT); 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(); toast.show();
} }
return true; 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; package net.pierrox.lightning_launcher.views;
import java.util.ArrayList;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -35,76 +33,28 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Scroller; import android.widget.Scroller;
import java.util.ArrayList;
public class MyViewPager extends ViewGroup { 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 * Indicates that the pager is in an idle, settled state. The current page
* is fully in view and no animation is in progress. * is fully in view and no animation is in progress.
*/ */
public static final int SCROLL_STATE_IDLE = 0; public static final int SCROLL_STATE_IDLE = 0;
/** /**
* Indicates that the pager is currently being dragged by the user. * Indicates that the pager is currently being dragged by the user.
*/ */
public static final int SCROLL_STATE_DRAGGING = 1; public static final int SCROLL_STATE_DRAGGING = 1;
/** /**
* Indicates that the pager is in the process of settling to a final position. * Indicates that the pager is in the process of settling to a final position.
*/ */
public static final int SCROLL_STATE_SETTLING = 2; 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); protected final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>(2);
private OnPageChangeListener mOnPageChangeListener; private OnPageChangeListener mOnPageChangeListener;
private int mScrollState = SCROLL_STATE_IDLE; private int mScrollState = SCROLL_STATE_IDLE;
private Scroller mScroller; private Scroller mScroller;
private int mCurItem; private int mCurItem;
private boolean mScrolling; private boolean mScrolling;
private int mChildWidthMeasureSpec; private int mChildWidthMeasureSpec;
private int mChildHeightMeasureSpec; private int mChildHeightMeasureSpec;
private boolean mIsBeingDragged; private boolean mIsBeingDragged;
@ -113,22 +63,20 @@ public class MyViewPager extends ViewGroup {
private float mInitialMotionX; private float mInitialMotionX;
private float mLastMotionX; private float mLastMotionX;
private float mLastMotionY; private float mLastMotionY;
private VelocityTracker mVelocityTracker; private VelocityTracker mVelocityTracker;
private int mMinimumVelocity; private int mMinimumVelocity;
private int mMaximumVelocity; private int mMaximumVelocity;
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initViewPager();
}
public MyViewPager(Context context, AttributeSet attrs) {
@Override super(context, attrs);
protected void onFinishInflate() {
initPagerItems(); initViewPager();
} }
@Override
protected void onFinishInflate() {
initPagerItems();
}
@Override @Override
public void removeViewAt(int index) { public void removeViewAt(int index) {
@ -138,11 +86,11 @@ public class MyViewPager extends ViewGroup {
protected void initPagerItems() { protected void initPagerItems() {
mItems.clear(); mItems.clear();
int n=getChildCount(); int n = getChildCount();
int index = 0; int index = 0;
for(int i=0; i<n; i++) { for (int i = 0; i < n; i++) {
View view = getChildAt(i); View view = getChildAt(i);
if(view.getVisibility() == VISIBLE) { if (view.getVisibility() == VISIBLE) {
ItemInfo ii = new ItemInfo(); ItemInfo ii = new ItemInfo();
ii.v = view; ii.v = view;
ii.position = index++; ii.position = index++;
@ -151,14 +99,13 @@ public class MyViewPager extends ViewGroup {
} }
} }
int size = mItems.size() - 1; int size = mItems.size() - 1;
if(mCurItem > size) { if (mCurItem > size) {
setCurrentItemInternal(size, false, true); setCurrentItemInternal(size, false, true);
} }
requestLayout(); requestLayout();
} }
@Override
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// For simple implementation, or internal size is always 0. // For simple implementation, or internal size is always 0.
// We depend on the container to specify the layout size of // 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); super.onSizeChanged(w, h, oldw, oldh);
// Make sure scroll position is set correctly. // Make sure scroll position is set correctly.
int scrollPos = mCurItem*w; int scrollPos = mCurItem * w;
if (scrollPos != getScrollX()) { if (scrollPos != getScrollX()) {
completeScroll(); completeScroll();
scrollTo(scrollPos, getScrollY()); scrollTo(scrollPos, getScrollY());
} }
} }
@Override @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount(); final int count = getChildCount();
final int width = r-l; final int width = r - l;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
View child = getChildAt(i); View child = getChildAt(i);
ItemInfo ii; ItemInfo ii;
if (child.getVisibility() != GONE && (ii=infoForChild(child)) != null) { if (child.getVisibility() != GONE && (ii = infoForChild(child)) != null) {
int loff = width*ii.position; int loff = width * ii.position;
int childLeft = getPaddingLeft() + loff; int childLeft = getPaddingLeft() + loff;
int childTop = getPaddingTop(); int childTop = getPaddingTop();
child.layout(childLeft, childTop, child.layout(childLeft, childTop,
@ -214,8 +161,8 @@ public class MyViewPager extends ViewGroup {
} }
} }
} }
@Override @Override
public boolean onInterceptTouchEvent(MotionEvent ev) { public boolean onInterceptTouchEvent(MotionEvent ev) {
/* /*
* This method JUST determines whether we want to intercept the motion. * 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 x = ev.getX();
final float dx = x - mLastMotionX; final float dx = x - mLastMotionX;
final float xDiff = Math.abs(dx); 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 * The only time we want to intercept motion events is if we are in the
* drag mode. * drag mode.
*/ */
return mIsBeingDragged; return mIsBeingDragged;
} }
@ -377,13 +323,13 @@ public class MyViewPager extends ViewGroup {
if (mIsBeingDragged) { if (mIsBeingDragged) {
final VelocityTracker velocityTracker = mVelocityTracker; final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int)velocityTracker.getYVelocity(); int initialVelocity = (int) velocityTracker.getYVelocity();
if ((Math.abs(initialVelocity) > mMinimumVelocity) if ((Math.abs(initialVelocity) > mMinimumVelocity)
|| Math.abs(mInitialMotionX-mLastMotionX) >= (getWidth()/3)) { || Math.abs(mInitialMotionX - mLastMotionX) >= (getWidth() / 3)) {
if (mLastMotionX > mInitialMotionX) { if (mLastMotionX > mInitialMotionX) {
setCurrentItemInternal(mCurItem-1, true, true); setCurrentItemInternal(mCurItem - 1, true, true);
} else { } else {
setCurrentItemInternal(mCurItem+1, true, true); setCurrentItemInternal(mCurItem + 1, true, true);
} }
} else { } else {
setCurrentItemInternal(mCurItem, true, true); setCurrentItemInternal(mCurItem, true, true);
@ -401,7 +347,7 @@ public class MyViewPager extends ViewGroup {
} }
return true; return true;
} }
@Override @Override
public void computeScroll() { public void computeScroll() {
if (!mScroller.isFinished()) { if (!mScroller.isFinished()) {
@ -432,40 +378,40 @@ public class MyViewPager extends ViewGroup {
// Done with scroll, clean up state. // Done with scroll, clean up state.
completeScroll(); completeScroll();
} }
public void setOnPageChangeListener(OnPageChangeListener listener) { public void setOnPageChangeListener(OnPageChangeListener listener) {
mOnPageChangeListener = listener; mOnPageChangeListener = listener;
} }
public int getCurrentItem() {
return mCurItem;
}
public void setCurrentItem(int item) { public void setCurrentItem(int item) {
setCurrentItemInternal(item, true, false); setCurrentItemInternal(item, true, false);
} }
public View getCurrentView() {
return mItems.get(mCurItem).v;
}
public void setCurrentView(View v) { public void setCurrentView(View v) {
for(ItemInfo ii : mItems) { for (ItemInfo ii : mItems) {
if(ii.v == v) { if (ii.v == v) {
setCurrentItemInternal(ii.position, false, false); setCurrentItemInternal(ii.position, false, false);
break; break;
} }
} }
} }
public int getCurrentItem() {
return mCurItem;
}
public View getCurrentView() {
return mItems.get(mCurItem).v;
}
public boolean isFirst() { public boolean isFirst() {
return mCurItem == 0; return mCurItem == 0;
} }
public boolean isLast() { public boolean isLast() {
return mCurItem == mItems.size()-1; return mCurItem == mItems.size() - 1;
} }
private void endDrag() { private void endDrag() {
mIsBeingDragged = false; mIsBeingDragged = false;
mIsUnableToDrag = false; mIsUnableToDrag = false;
@ -475,7 +421,7 @@ public class MyViewPager extends ViewGroup {
mVelocityTracker = null; mVelocityTracker = null;
} }
} }
private void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) { private void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {
if (!always && mCurItem == item && mItems.size() != 0) { if (!always && mCurItem == item && mItems.size() != 0) {
return; return;
@ -488,18 +434,18 @@ public class MyViewPager extends ViewGroup {
item = size; 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 // We are doing a jump by more than one page. To avoid
// glitches, we want to keep all current pages in the view // glitches, we want to keep all current pages in the view
// until the scroll ends. // 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; mItems.get(i).scrolling = true;
} }
} }
final boolean dispatchSelected = mCurItem != item; final boolean dispatchSelected = mCurItem != item;
mCurItem = item; mCurItem = item;
if (smoothScroll) { if (smoothScroll) {
smoothScrollTo(getWidth()*item, 0); smoothScrollTo(getWidth() * item, 0);
if (dispatchSelected && mOnPageChangeListener != null) { if (dispatchSelected && mOnPageChangeListener != null) {
mOnPageChangeListener.onPageSelected(item); mOnPageChangeListener.onPageSelected(item);
} }
@ -508,11 +454,11 @@ public class MyViewPager extends ViewGroup {
mOnPageChangeListener.onPageSelected(item); mOnPageChangeListener.onPageSelected(item);
} }
completeScroll(); completeScroll();
scrollTo(getWidth()*item, 0); scrollTo(getWidth() * item, 0);
} }
} }
private void initViewPager() { private void initViewPager() {
setWillNotDraw(false); setWillNotDraw(false);
mScroller = new Scroller(getContext()); mScroller = new Scroller(getContext());
final ViewConfiguration configuration = ViewConfiguration.get(getContext()); final ViewConfiguration configuration = ViewConfiguration.get(getContext());
@ -521,13 +467,13 @@ public class MyViewPager extends ViewGroup {
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
} }
private ItemInfo infoForChild(View child) { private ItemInfo infoForChild(View child) {
for(ItemInfo ii : mItems) { for (ItemInfo ii : mItems) {
if(ii.v == child) return ii; if (ii.v == child) return ii;
} }
return null; return null;
} }
/** /**
* Like {@link View#scrollBy}, but scroll smoothly instead of immediately. * 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); mScroller.startScroll(sx, sy, dx, dy);
invalidate(); invalidate();
} }
private void completeScroll() { private void completeScroll() {
if (mScrolling) { if (mScrolling) {
// Done with scroll, no longer want to cache view drawing. // Done with scroll, no longer want to cache view drawing.
mScroller.abortAnimation(); mScroller.abortAnimation();
@ -568,15 +514,15 @@ public class MyViewPager extends ViewGroup {
setScrollState(SCROLL_STATE_IDLE); setScrollState(SCROLL_STATE_IDLE);
} }
mScrolling = false; mScrolling = false;
for (int i=0; i<mItems.size(); i++) { for (int i = 0; i < mItems.size(); i++) {
ItemInfo ii = mItems.get(i); ItemInfo ii = mItems.get(i);
if (ii.scrolling) { if (ii.scrolling) {
ii.scrolling = false; ii.scrolling = false;
} }
} }
} }
private void setScrollState(int newState) { private void setScrollState(int newState) {
if (mScrollState == newState) { if (mScrollState == newState) {
return; return;
} }
@ -586,4 +532,47 @@ public class MyViewPager extends ViewGroup {
mOnPageChangeListener.onPageScrollStateChanged(newState); 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; import java.util.ArrayList;
/** /**
* Created by pierrot on 18/03/2015. * Created by pierrot on 18/03/2015.
*/ */
public class SnappingContext { public class SnappingContext {
public static final int SNAP_LEFT = 1; public static final int SNAP_LEFT = 1;
public static final int SNAP_RIGHT = 2; 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_CENTER = 16;
public static final int SNAP_ALL = 31; public static final int SNAP_ALL = 31;
private int snap_what; private final int snap_what;
private float touch_slop; private final float touch_slop;
private final ItemView my_item_view;
public float min_dx = Float.MAX_VALUE; public float min_dx = Float.MAX_VALUE;
public float min_dy = Float.MAX_VALUE; public float min_dy = Float.MAX_VALUE;
public float anchor_x = Float.MAX_VALUE; public float anchor_x = Float.MAX_VALUE;
public float anchor_y = Float.MAX_VALUE; public float anchor_y = Float.MAX_VALUE;
public ItemLayout item_layout;
private ArrayList<ItemView> snapped_items; private ArrayList<ItemView> snapped_items;
private ArrayList<RectF> snapped_bounds; 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) { public SnappingContext(ItemView my_item_view, float touch_slop, int snap_what) {
this.my_item_view = my_item_view; this.my_item_view = my_item_view;
@ -67,7 +67,7 @@ public class SnappingContext {
} }
public void stop() { public void stop() {
for(ItemView i : snapped_items) { for (ItemView i : snapped_items) {
i.setFocused(false); i.setFocused(false);
} }
my_item_view.setFocused(false); my_item_view.setFocused(false);
@ -79,7 +79,7 @@ public class SnappingContext {
public void computeSnaps(Matrix item_transform) { public void computeSnaps(Matrix item_transform) {
Rect hr = new Rect(); Rect hr = new Rect();
item_layout.getHitRect(hr); item_layout.getHitRect(hr);
RectF screen_bounds=new RectF(hr); RectF screen_bounds = new RectF(hr);
// compute corners and center of the moving item // compute corners and center of the moving item
RectF bounds_from = new RectF(); RectF bounds_from = new RectF();
@ -87,7 +87,7 @@ public class SnappingContext {
computeItemViewSnapBounds(my_item_view, item_transform, bounds_from); computeItemViewSnapBounds(my_item_view, item_transform, bounds_from);
for(ItemView i : snapped_items) { for (ItemView i : snapped_items) {
i.setFocused(false); i.setFocused(false);
} }
my_item_view.setFocused(false); my_item_view.setFocused(false);
@ -100,9 +100,9 @@ public class SnappingContext {
snapped_bounds.clear(); snapped_bounds.clear();
// first pass to compute the minimum distance // 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); View v = item_layout.getChildAt(n);
if(v instanceof ItemView) { if (v instanceof ItemView) {
ItemView i = (ItemView) v; ItemView i = (ItemView) v;
if (i.isSelected() || i == my_item_view) continue; 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 // 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); View v = item_layout.getChildAt(n);
if(v instanceof ItemView) { if (v instanceof ItemView) {
ItemView i = (ItemView) v; ItemView i = (ItemView) v;
if (i.isSelected() || i == my_item_view) continue; 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); i.setFocused(true);
} }
} }
@ -144,7 +144,7 @@ public class SnappingContext {
public void applySnaps(Matrix item_transform) { public void applySnaps(Matrix item_transform) {
item_layout.setSnappingData(anchor_x, anchor_y, snapped_bounds); item_layout.setSnappingData(anchor_x, anchor_y, snapped_bounds);
if(snapped_bounds.size() > 0) { if (snapped_bounds.size() > 0) {
RectF bounds_to = new RectF(); RectF bounds_to = new RectF();
computeItemViewSnapBounds(my_item_view, item_transform, bounds_to); computeItemViewSnapBounds(my_item_view, item_transform, bounds_to);
snapped_bounds.add(bounds_to); snapped_bounds.add(bounds_to);
@ -156,7 +156,7 @@ public class SnappingContext {
Item item = itemView.getItem(); Item item = itemView.getItem();
float cw = item_layout.getCellWidth(); float cw = item_layout.getCellWidth();
float ch = item_layout.getCellHeight(); float ch = item_layout.getCellHeight();
if(item.getItemConfig().onGrid) { if (item.getItemConfig().onGrid) {
outBounds.set(item.getCell()); outBounds.set(item.getCell());
outBounds.left *= cw; outBounds.left *= cw;
outBounds.right *= cw; outBounds.right *= cw;
@ -166,34 +166,34 @@ public class SnappingContext {
outBounds.set(0, 0, item.getViewWidth(), item.getViewHeight()); outBounds.set(0, 0, item.getViewWidth(), item.getViewHeight());
itemTransform.mapRect(outBounds); itemTransform.mapRect(outBounds);
} }
Matrix t=item_layout.getTransformForItemView(itemView); Matrix t = item_layout.getTransformForItemView(itemView);
if(t!=null) { if (t != null) {
t.mapRect(outBounds); t.mapRect(outBounds);
} }
if(item.getClass() == StopPoint.class) { if (item.getClass() == StopPoint.class) {
outBounds.offset(-outBounds.width()/2, -outBounds.height()/2); outBounds.offset(-outBounds.width() / 2, -outBounds.height() / 2);
} }
} }
private boolean checkSnap(RectF from, RectF to) { private boolean checkSnap(RectF from, RectF to) {
boolean snap = false; 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.left);
snap |= doesSnapX(from.left, to.right); 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.right);
snap |= doesSnapX(from.right, to.left); 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 |= doesSnapX(from.centerX(), to.centerX());
snap |= doesSnapY(from.centerY(), to.centerY()); 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.top);
snap |= doesSnapY(from.top, to.bottom); 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.bottom);
snap |= doesSnapY(from.bottom, to.top); snap |= doesSnapY(from.bottom, to.top);
} }
@ -202,9 +202,9 @@ public class SnappingContext {
} }
private boolean doesSnapX(float from, float to) { private boolean doesSnapX(float from, float to) {
float diff = to-from; float diff = to - from;
float abs_diff = Math.abs(diff); 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; min_dx = diff;
anchor_x = to; anchor_x = to;
return true; return true;
@ -214,9 +214,9 @@ public class SnappingContext {
} }
private boolean doesSnapY(float from, float to) { private boolean doesSnapY(float from, float to) {
float diff = to-from; float diff = to - from;
float abs_diff = Math.abs(diff); 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; min_dy = diff;
anchor_y = to; anchor_y = to;
return true; 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. * translucent system UI modes.
*
*/ */
public class SystemBarTintManager { public class SystemBarTintManager {
@ -66,18 +65,17 @@ public class SystemBarTintManager {
* The default system bar tint color value. * The default system bar tint color value.
*/ */
public static final int DEFAULT_TINT_COLOR = 0x99000000; 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 SystemBarConfig mConfig;
private boolean mStatusBarAvailable = true;
private boolean mNavBarAvailable = true;
private boolean mStatusBarTintEnabled; private boolean mStatusBarTintEnabled;
private boolean mNavBarTintEnabled; private boolean mNavBarTintEnabled;
private View mStatusBarTintView; private View mStatusBarTintView;
private View mNavBarTintView; private View mNavBarTintView;
private Animation mStatusBarAnimEnter;
private Animation mStatusBarAnimExit;
/** /**
* Constructor. Call this in the host activity onCreate method after its * Constructor. Call this in the host activity onCreate method after its
* content view has been set. You should always create new instances when * content view has been set. You should always create new instances when
@ -105,33 +103,9 @@ public class SystemBarTintManager {
setupNavBarLayoutParams(); 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. * Enable tinting of the system navigation bar.
* * <p>
* If the platform does not have soft navigation keys, is running Jelly Bean * 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 * or earlier, or translucent system UI modes have not been enabled in either
* the theme or via window flags, then this method does nothing. * the theme or via window flags, then this method does nothing.
@ -295,6 +269,29 @@ public class SystemBarTintManager {
return mStatusBarTintEnabled; 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? * 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 * Class which describes system bar sizing and other characteristics for the current
* device configuration. * device configuration.
*
*/ */
public static class SystemBarConfig { 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_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
// private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; // private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
// private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; // 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 boolean mIsInPortrait;
private final int mStatusBarHeight; private final int mStatusBarHeight;
private final int mActionBarHeight; private final int mActionBarHeight;
private final boolean mHasNavigationBar; private final boolean mHasNavigationBar;
private final int mNavigationBarHeight; private final int mNavigationBarHeight;
// private final int mNavigationBarWidth; // private final int mNavigationBarWidth;
private final boolean mIsNavigationAtBottom; 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) { private SystemBarConfig(Window window) {
Resources res = window.getContext().getResources(); Resources res = window.getContext().getResources();
@ -387,16 +381,16 @@ public class SystemBarTintManager {
if (Build.VERSION.SDK_INT >= 28) { if (Build.VERSION.SDK_INT >= 28) {
WindowInsets windowInsets = window.getDecorView().getRootWindowInsets(); WindowInsets windowInsets = window.getDecorView().getRootWindowInsets();
if(windowInsets != null) { if (windowInsets != null) {
DisplayCutout cutout = windowInsets.getDisplayCutout(); DisplayCutout cutout = windowInsets.getDisplayCutout();
if(cutout != null) { if (cutout != null) {
sSafeInsetWidth = cutout.getSafeInsetLeft() + cutout.getSafeInsetRight(); sSafeInsetWidth = cutout.getSafeInsetLeft() + cutout.getSafeInsetRight();
sSafeInsetHeight = cutout.getSafeInsetTop() + cutout.getSafeInsetBottom(); sSafeInsetHeight = cutout.getSafeInsetTop() + cutout.getSafeInsetBottom();
} }
} }
} }
mIsNavigationAtBottom = realDm.widthPixels == dm.widthPixels; mIsNavigationAtBottom = realDm.widthPixels == dm.widthPixels;
if(mIsInPortrait || mIsNavigationAtBottom) { if (mIsInPortrait || mIsNavigationAtBottom) {
mNavigationBarHeight = realDm.heightPixels - dm.heightPixels - sSafeInsetHeight; mNavigationBarHeight = realDm.heightPixels - dm.heightPixels - sSafeInsetHeight;
} else { } else {
mNavigationBarHeight = realDm.widthPixels - dm.widthPixels - sSafeInsetWidth; mNavigationBarHeight = realDm.widthPixels - dm.widthPixels - sSafeInsetWidth;

View file

@ -13,11 +13,6 @@
package net.dinglisch.android.tasker; 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.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
@ -30,420 +25,406 @@ import android.os.PatternMatcher;
import android.os.Process; import android.os.Process;
import android.util.Log; 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 { public class TaskerIntent extends Intent {
// 3 Tasker versions // 3 Tasker versions
public final static String TASKER_PACKAGE = "net.dinglisch.android.tasker"; 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_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=";
// Play Store download URLs private final static String TASKER_MARKET_URL = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_MARKET;
public final static String MARKET_DOWNLOAD_URL_PREFIX = "market://details?id="; public final static String TASKER_PACKAGE_CUPCAKE = TASKER_PACKAGE + "cupcake";
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;
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";
// Content provider columns // Intent actions
public static final String PROVIDER_COL_NAME_EXTERNAL_ACCESS = "ext_access"; public final static String ACTION_TASK = TASKER_PACKAGE + ".ACTION_TASK";
public static final String PROVIDER_COL_NAME_ENABLED = "enabled"; public final static String ACTION_TASK_COMPLETE = TASKER_PACKAGE + ".ACTION_TASK_COMPLETE";
public final static String ACTION_TASK_SELECT = TASKER_PACKAGE + ".ACTION_TASK_SELECT";
// DEPRECATED, use EXTRA_VAR_NAMES_LIST, EXTRA_VAR_VALUES_LIST // Intent parameters
public final static String EXTRA_PARAM_LIST = "params"; 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 // Intent data
public final static String DEFAULT_ENCRYPTION_KEY = "default";
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";
private final static String ACTION_OPEN_PREFS = TASKER_PACKAGE + ".ACTION_OPEN_PREFS"; // For particular actions
public final static String EXTRA_OPEN_PREFS_TAB_NO = "tno"; public final static String ENCRYPTED_AFFIX = "tec";
private final static int MISC_PREFS_TAB_NO = 3; // 0 based 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 // 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 String TASKER_PREFS_URI = "content://" + TASKER_PACKAGE + "/prefs";
private final static int CUPCAKE_SDK_VERSION = 3;
// result values for TestSend private final static int CUPCAKE_SDK_VERSION = 3;
// NotInstalled: Tasker package not found on device // result values for TestSend
// 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 };
// -------------------------- 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"; public TaskerIntent() {
private final static String INTENT_VERSION_NUMBER = "1.1"; super(ACTION_TASK);
setRandomData();
putMetaExtras(getRandomString());
}
// Inclusive values // -------------------------- PUBLIC METHODS ---------------------------- //
private final static int MIN_PRIORITY = 0;
private final static int MAX_PRIORITY = 10;
// For generating random names
private static Random rand = new Random();
// Tracking state public TaskerIntent(String taskName) {
private int actionCount = 0; super(ACTION_TASK);
private int argCount; setRandomData();
putMetaExtras(taskName);
// -------------------------- PUBLIC METHODS ---------------------------- // }
public static int getMaxPriority() { public static int getMaxPriority() {
return MAX_PRIORITY; 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 ) {
}
try { // Tasker has different package names for Play Store and non- versions
context.getPackageManager().getPackageInfo( TASKER_PACKAGE_MARKET, 0 ); // for historical reasons
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 ) {
Status result; public static boolean validatePriority(int pri) {
return (
if ( ! taskerInstalled( c ) ) (pri >= MIN_PRIORITY) ||
result = Status.NotInstalled; (pri <= MAX_PRIORITY)
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;
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 ) { String foundPackage = null;
return ( getInstalledTaskerPackage( context ) != null );
}
// Use with startActivity to retrieve Tasker from Android market try {
public static Intent getTaskerInstallIntent( boolean marketFlag ) { context.getPackageManager().getPackageInfo(TASKER_PACKAGE, 0);
foundPackage = TASKER_PACKAGE;
return new Intent( } catch (PackageManager.NameNotFoundException e) {
Intent.ACTION_VIEW, }
Uri.parse(
marketFlag ?
( ( SDKVersion() == CUPCAKE_SDK_VERSION ) ? TASKER_MARKET_URL_CUPCAKE : TASKER_MARKET_URL ) :
TASKER_DOWNLOAD_URL
)
);
}
public static int SDKVersion() { try {
try { context.getPackageManager().getPackageInfo(TASKER_PACKAGE_MARKET, 0);
Field f = android.os.Build.VERSION.class.getField( "SDK_INT" ); foundPackage = TASKER_PACKAGE_MARKET;
return f.getInt( null ); } catch (PackageManager.NameNotFoundException e) {
} }
catch ( Exception e ) {
return CUPCAKE_SDK_VERSION;
}
}
public static IntentFilter getCompletionFilter( String taskName ) {
IntentFilter filter = new IntentFilter( TaskerIntent.ACTION_TASK_COMPLETE ); return foundPackage;
}
filter.addDataScheme( TASK_NAME_DATA_SCHEME ); // Check if Tasker installed
filter.addDataPath( taskName, PatternMatcher.PATTERN_LITERAL );
return filter;
}
public static Intent getTaskSelectIntent() { public static Status testStatus(Context c) {
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;
}
// Get an intent that will bring up the Tasker prefs screen with the External Access control(s) Status result;
// 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 );
}
// ------------------------------------- INSTANCE METHODS ----------------------------- // if (!taskerInstalled(c))
result = Status.NotInstalled;
public TaskerIntent() { else if (!havePermission(c))
super( ACTION_TASK ); result = Status.NoPermission;
setRandomData(); else if (!TaskerIntent.prefSet(c, PROVIDER_COL_NAME_ENABLED))
putMetaExtras( getRandomString() ); result = Status.NotEnabled;
} else if (!TaskerIntent.prefSet(c, PROVIDER_COL_NAME_EXTERNAL_ACCESS))
result = Status.AccessBlocked;
public TaskerIntent( String taskName ) { else if (!new TaskerIntent("").receiverExists(c))
super( ACTION_TASK ); result = Status.NoReceiver;
setRandomData(); else
putMetaExtras( taskName ); result = Status.OK;
}
public TaskerIntent setTaskPriority( int priority ) { return result;
}
if ( validatePriority( priority ) ) public static boolean taskerInstalled(Context context) {
putExtra( EXTRA_TASK_PRIORITY, priority ); return (getInstalledTaskerPackage(context) != null);
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;
}
// Arbitrary specification of (local) variable names and values // Use with startActivity to retrieve Tasker from Android market
public TaskerIntent addLocalVariable( String name, String value ) { public static Intent getTaskerInstallIntent(boolean marketFlag) {
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 ); return new Intent(
putStringArrayListExtra( EXTRA_VAR_VALUES_LIST, values ); Intent.ACTION_VIEW,
} Uri.parse(
marketFlag ?
((SDKVersion() == CUPCAKE_SDK_VERSION) ? TASKER_MARKET_URL_CUPCAKE : TASKER_MARKET_URL) :
TASKER_DOWNLOAD_URL
)
);
}
names.add( name ); public static int SDKVersion() {
values.add( value ); 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 ) { IntentFilter filter = new IntentFilter(TaskerIntent.ACTION_TASK_COMPLETE);
actionCount++;
argCount = 1;
Bundle actionBundle = new Bundle();
actionBundle.putInt( ACTION_CODE, code );
// Add action bundle to intent filter.addDataScheme(TASK_NAME_DATA_SCHEME);
putExtra( EXTRA_ACTION_INDEX_PREFIX + Integer.toString( actionCount ), actionBundle ); filter.addDataPath(taskName, PatternMatcher.PATTERN_LITERAL);
return this; return filter;
} }
// string arg
public TaskerIntent addArg( String arg ) {
Bundle b = getActionBundle(); // public access deprecated, use TaskerIntent.testSend() instead
if ( b != null ) public static Intent getTaskSelectIntent() {
b.putString( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg ); return new Intent(ACTION_TASK_SELECT).
setFlags(
return this; Intent.FLAG_ACTIVITY_NO_USER_ACTION |
} Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
Intent.FLAG_ACTIVITY_NO_HISTORY
// int arg );
public TaskerIntent addArg( int arg ) { }
Bundle b = getActionBundle();
if ( b != null ) // Get an intent that will bring up the Tasker prefs screen with the External Access control(s)
b.putInt( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg ); // Probably you want to use startActivity or startActivityForResult with it
return this;
}
// boolean arg
public TaskerIntent addArg( boolean arg ) {
Bundle b = getActionBundle();
if ( b != null ) public static boolean havePermission(Context c) {
b.putBoolean( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg ); return c.checkPermission(PERMISSION_RUN_TASKS, Process.myPid(), Process.myUid()) ==
PackageManager.PERMISSION_GRANTED;
return this; }
}
// Application arg // ------------------------------------- INSTANCE METHODS ----------------------------- //
public TaskerIntent addArg( String pkg, String cls ) {
Bundle b = getActionBundle();
if ( b != null ) { public static Intent getExternalAccessPrefsIntent() {
StringBuilder builder = new StringBuilder(); return new Intent(ACTION_OPEN_PREFS).putExtra(EXTRA_OPEN_PREFS_TAB_NO, MISC_PREFS_TAB_NO);
builder.append( APP_ARG_PREFIX ). }
append( pkg ). append( "," ). append( cls );
b.putString( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), b.toString() );
}
return this;
}
public IntentFilter getCompletionFilter() { private static boolean prefSet(Context context, String col) {
return getCompletionFilter( getTaskName() );
}
public String getTaskName() { String[] proj = new String[]{col};
return getStringExtra( EXTRA_TASK_NAME );
}
public boolean receiverExists( Context context ) { Cursor c = context.getContentResolver().query(Uri.parse(TASKER_PREFS_URI), proj, null, null, null);
List<ResolveInfo> recs = context.getPackageManager().queryBroadcastReceivers( this, 0 );
return (
( recs != null ) &&
( recs.size() > 0 )
);
}
// -------------------- PRIVATE METHODS -------------------- // boolean acceptingFlag = false;
private String getRandomString() {
return Long.toString( rand.nextLong() );
}
// so that if multiple TaskerIntents are used in PendingIntents there's virtually no if (c == null)
// clash chance Log.w(TAG, "no cursor for " + TASKER_PREFS_URI);
private void setRandomData() { else {
setData( Uri.parse( TASK_ID_SCHEME + ":" + getRandomString() ) ); c.moveToFirst();
}
private Bundle getActionBundle() {
Bundle toReturn = null; if (Boolean.TRUE.toString().equals(c.getString(0)))
acceptingFlag = true;
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 ( this.hasExtra( key ) ) c.close();
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 return acceptingFlag;
}
private static boolean prefSet( Context context, String col ) {
String [] proj = new String [] { col };
Cursor c = context.getContentResolver().query( Uri.parse( TASKER_PREFS_URI ), proj, null, null, null ); public TaskerIntent setTaskPriority(int priority) {
boolean acceptingFlag = false; if (validatePriority(priority))
putExtra(EXTRA_TASK_PRIORITY, priority);
if ( c == null ) else
Log.w( TAG, "no cursor for " + TASKER_PREFS_URI ); Log.e(TAG, "priority out of range: " + MIN_PRIORITY + ":" + MAX_PRIORITY);
else {
c.moveToFirst();
if ( Boolean.TRUE.toString().equals( c.getString( 0 ) ) )
acceptingFlag = true;
c.close(); return this;
} }
return acceptingFlag; // 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. * This drawable that draws a simple white and gray chessboard pattern.
* It's pattern you will often see as a background behind a * It's pattern you will often see as a background behind a
* partly transparent image in many applications. * partly transparent image in many applications.
*
* @author Daniel Nilsson * @author Daniel Nilsson
*/ */
public class AlphaPatternDrawable extends Drawable { 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(); * Bitmap in which the pattern will be cahched.
private Paint mPaintGray = new Paint(); */
private int numRectanglesHorizontal;
private int numRectanglesVertical;
/**
* Bitmap in which the pattern will be cahched.
*/
// private Bitmap mBitmap; // private Bitmap mBitmap;
public AlphaPatternDrawable(int rectangleSize) {
mRectangleSize = rectangleSize;
mPaintWhite.setColor(0xffffffff);
mPaintGray.setColor(0xffcbcbcb);
}
public AlphaPatternDrawable(int rectangleSize) { @Override
mRectangleSize = rectangleSize; public void draw(Canvas canvas) {
mPaintWhite.setColor(0xffffffff);
mPaintGray.setColor(0xffcbcbcb);
}
@Override
public void draw(Canvas canvas) {
// canvas.drawBitmap(mBitmap, null, getBounds(), mPaint); // 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; Rect bounds = getBounds();
for (int j = 0; j <= numRectanglesHorizontal; j++) {
r.top = i * mRectangleSize; canvas.clipRect(bounds);
r.left = j * mRectangleSize; canvas.translate(bounds.left, bounds.top);
r.bottom = r.top + mRectangleSize;
r.right = r.left + mRectangleSize;
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.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
canvas.translate(-bounds.left, -bounds.top);
}
@Override isWhite = !isWhite;
public int getOpacity() { }
return 0;
}
@Override verticalStartWhite = !verticalStartWhite;
public void setAlpha(int alpha) {
}
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."); // throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
} }
@Override @Override
public void setColorFilter(ColorFilter cf) { public void setColorFilter(ColorFilter cf) {
// throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable."); // throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
} }
@Override @Override
protected void onBoundsChange(Rect bounds) { protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds); super.onBoundsChange(bounds);
int height = bounds.height(); int height = bounds.height();
int width = bounds.width(); int width = bounds.width();
numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize)); numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
numRectanglesVertical = (int) Math.ceil(height / mRectangleSize); numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
// generatePatternBitmap(); // generatePatternBitmap();
} }
// /** // /**
// * This will generate a bitmap with the pattern // * 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.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import net.pierrox.lightning_launcher.R; import net.pierrox.lightning_launcher.R;
public class ColorPickerDialog public class ColorPickerDialog
extends extends
Dialog Dialog
implements implements
ColorPickerView.OnColorChangedListener, ColorPickerView.OnColorChangedListener,
View.OnClickListener, DialogInterface.OnCancelListener { View.OnClickListener, DialogInterface.OnCancelListener {
private ColorPickerView mColorPicker; private ColorPickerView mColorPicker;
private ColorPickerPanelView mOldColor; private ColorPickerPanelView mOldColor;
private ColorPickerPanelView mNewColor; private ColorPickerPanelView mNewColor;
private EditText mHexEditor; private EditText mHexEditor;
private OnColorChangedListener mListener; private OnColorChangedListener mListener;
public ColorPickerDialog(Context context, int initialColor) {
super(context);
init(initialColor);
}
@Override @Override
public void onCancel(DialogInterface dialogInterface) { public void onCancel(DialogInterface dialogInterface) {
if(mListener != null) mListener.onColorDialogCanceled(); if (mListener != null) mListener.onColorDialogCanceled();
} }
public interface OnColorChangedListener { private void init(int color) {
public void onColorChanged(int color); // To fight color banding.
public void onColorDialogSelected(int color); getWindow().setFormat(PixelFormat.RGBA_8888);
public void onColorDialogCanceled();
}
public ColorPickerDialog(Context context, int initialColor) {
super(context);
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) { View layout = inflater.inflate(R.layout.dialog_color_picker, null);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dialog_color_picker, null);
setContentView(layout); setContentView(layout);
setTitle(R.string.dialog_color_picker); 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 "";
}
boolean ok=true; mColorPicker = layout.findViewById(R.id.color_picker_view);
for (int i = start; i < end; i++) { mOldColor = layout.findViewById(R.id.old_color_panel);
char c = source.charAt(i); mNewColor = layout.findViewById(R.id.new_color_panel);
if ( !((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F')) ) { mHexEditor = layout.findViewById(R.id.hex_editor);
ok=false; mHexEditor.clearFocus();
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 InputFilter filter = new InputFilter() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) { @Override
// pass 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( // ((LinearLayout) mOldColor.getParent()).setPadding(
// Math.round(mColorPicker.getDrawingOffset()), // Math.round(mColorPicker.getDrawingOffset()),
// 0, // 0,
// Math.round(mColorPicker.getDrawingOffset()), // Math.round(mColorPicker.getDrawingOffset()),
// 0 // 0
// ); // );
mOldColor.setOnClickListener(this); mOldColor.setOnClickListener(this);
mNewColor.setOnClickListener(this); mNewColor.setOnClickListener(this);
mColorPicker.setOnColorChangedListener(this); mColorPicker.setOnColorChangedListener(this);
mOldColor.setColor(color); mOldColor.setColor(color);
mColorPicker.setColor(color, true); mColorPicker.setColor(color, true);
setOnCancelListener(this); setOnCancelListener(this);
} }
@Override @Override
public void onColorChanged(int color) { public void onColorChanged(int color) {
mNewColor.setColor(color); mNewColor.setColor(color);
/* /*
if (mListener != null) { if (mListener != null) {
@ -158,37 +153,38 @@ public class ColorPickerDialog
} }
*/ */
String hex=Integer.toHexString(color); String hex = Integer.toHexString(color);
mHexEditor.setText(fillHex(hex));
}
private String fillHex(String hex) {
while(hex.length()<8) {
hex='0'+hex;
}
return hex;
}
public void setAlphaSliderVisible(boolean visible) { mHexEditor.setText(fillHex(hex));
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() { private String fillHex(String hex) {
return mColorPicker.getColor(); while (hex.length() < 8) {
} hex = '0' + hex;
}
return hex;
}
@Override public void setAlphaSliderVisible(boolean visible) {
public void onClick(View v) { 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) { if (mListener != null) {
int color = mNewColor.getColor(); int color = mNewColor.getColor();
int id = v.getId(); int id = v.getId();
@ -200,8 +196,16 @@ public class ColorPickerDialog
mListener.onColorDialogCanceled(); mListener.onColorDialogCanceled();
} }
} }
dismiss(); dismiss();
} }
public interface OnColorChangedListener {
void onColorChanged(int color);
void onColorDialogSelected(int color);
void onColorDialogCanceled();
}
// //
// @Override // @Override
// public Bundle onSaveInstanceState() { // public Bundle onSaveInstanceState() {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -27,10 +27,6 @@ import java.util.HashMap;
public class IconPack { 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) { 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); boolean result = doApplyIconPackInBackground(context, package_name, page, item_id);
doApplyIconPackPostExecute(page, item_id); doApplyIconPackPostExecute(page, item_id);
@ -53,7 +49,7 @@ public class IconPack {
@Override @Override
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
doApplyIconPackPostExecute(page, item_id); doApplyIconPackPostExecute(page, item_id);
if(listener != null) { if (listener != null) {
listener.onPackApplied(result); listener.onPackApplied(result);
} }
@ -70,9 +66,9 @@ public class IconPack {
page.config.defaultShortcutConfig.iconEffectScale = 1; page.config.defaultShortcutConfig.iconEffectScale = 1;
for(Item i : page.items) { for (Item i : page.items) {
if(i.getClass() == Shortcut.class) { if (i.getClass() == Shortcut.class) {
Shortcut s = (Shortcut)i; Shortcut s = (Shortcut) i;
s.deleteCustomIconFiles(icon_dir); s.deleteCustomIconFiles(icon_dir);
s.getShortcutConfig().iconEffectScale = 1; s.getShortcutConfig().iconEffectScale = 1;
} }
@ -96,13 +92,14 @@ public class IconPack {
// build the cache of icon name -> drawable id (legacy way) // build the cache of icon name -> drawable id (legacy way)
HashMap<String, Integer> icon_name_ids = new HashMap<String, Integer>(); 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); String[] icon_names = res.getStringArray(icon_pack_res_id);
for(String icon_name : icon_names) { for (String icon_name : icon_names) {
try { try {
int drawable_res_id = res.getIdentifier(icon_name, "drawable", package_name); 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)); if (drawable_res_id != 0)
} catch(Resources.NotFoundException e) { icon_name_ids.put(icon_name, Integer.valueOf(drawable_res_id));
} catch (Resources.NotFoundException e) {
// pass, error in input array // 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 // build the cache of componentname -> drawable id and load icon layers if available
HashMap<String, Integer> component_name_ids = new HashMap<String, Integer>(); HashMap<String, Integer> component_name_ids = new HashMap<String, Integer>();
ArrayList<Bitmap> icon_effect_back = new ArrayList<Bitmap>(); 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; float icon_effect_scale = 1;
InputStream appfilter_is = null; InputStream appfilter_is = null;
try { try {
XmlPullParser parser; XmlPullParser parser;
int appfilter_id = icon_pack.getResources().getIdentifier("appfilter", "xml", package_name); 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); parser = icon_pack.getResources().getXml(appfilter_id);
} else { } else {
try { try {
@ -125,12 +122,12 @@ public class IconPack {
parser = Xml.newPullParser(); parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(appfilter_is, null); parser.setInput(appfilter_is, null);
} catch(IOException e) { } catch (IOException e) {
parser = null; parser = null;
} }
} }
if(parser == null) { if (parser == null) {
return false; return false;
} }
@ -140,32 +137,32 @@ public class IconPack {
String name = parser.getName(); String name = parser.getName();
if (name.equals("iconback")) { if (name.equals("iconback")) {
String n = parser.getAttributeValue(null, "img"); String n = parser.getAttributeValue(null, "img");
if(n == null) { if (n == null) {
for(int i=1; i<30; i++) { for (int i = 1; i < 30; i++) {
n = parser.getAttributeValue(null, "img"+i); n = parser.getAttributeValue(null, "img" + i);
if(n == null) { if (n == null) {
break; break;
} }
Bitmap b = loadBitmapFromDrawable(res, package_name, n); Bitmap b = loadBitmapFromDrawable(res, package_name, n);
if(b != null) { if (b != null) {
icon_effect_back.add(b); icon_effect_back.add(b);
} }
} }
} else { } else {
Bitmap b = loadBitmapFromDrawable(res, package_name, n); Bitmap b = loadBitmapFromDrawable(res, package_name, n);
if(b != null) { if (b != null) {
icon_effect_back.add(b); icon_effect_back.add(b);
} }
} }
} else if (name.equals("iconupon")) { } else if (name.equals("iconupon")) {
String n = parser.getAttributeValue(null, "img"); String n = parser.getAttributeValue(null, "img");
if(n == null) { if (n == null) {
n = parser.getAttributeValue(null, "img1"); n = parser.getAttributeValue(null, "img1");
} }
icon_effect_over = loadBitmapFromDrawable(res, package_name, n); icon_effect_over = loadBitmapFromDrawable(res, package_name, n);
} else if (name.equals("iconmask")) { } else if (name.equals("iconmask")) {
String n = parser.getAttributeValue(null, "img"); String n = parser.getAttributeValue(null, "img");
if(n == null) { if (n == null) {
n = parser.getAttributeValue(null, "img1"); n = parser.getAttributeValue(null, "img1");
} }
icon_effect_mask = loadBitmapFromDrawable(res, package_name, n); icon_effect_mask = loadBitmapFromDrawable(res, package_name, n);
@ -174,16 +171,17 @@ public class IconPack {
} else if (name.equals("item")) { } else if (name.equals("item")) {
String component = parser.getAttributeValue(null, "component"); String component = parser.getAttributeValue(null, "component");
String drawable = parser.getAttributeValue(null, "drawable"); String drawable = parser.getAttributeValue(null, "drawable");
try { try {
String component_name = component.substring(component.indexOf('{')+1, component.indexOf('}')); String component_name = component.substring(component.indexOf('{') + 1, component.indexOf('}'));
if(component_name.indexOf('/') == -1) { if (component_name.indexOf('/') == -1) {
component_name = component_name.substring(0, component_name.lastIndexOf('.')-1) + "/" + component_name; component_name = component_name.substring(0, component_name.lastIndexOf('.') - 1) + "/" + component_name;
} }
ComponentName cn = ComponentName.unflattenFromString(component_name); ComponentName cn = ComponentName.unflattenFromString(component_name);
int drawable_res_id = res.getIdentifier(drawable, "drawable", package_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)); if (drawable_res_id != 0)
} catch(Exception e) { component_name_ids.put(cn.flattenToString(), Integer.valueOf(drawable_res_id));
} catch (Exception e) {
Log.i("LL", "unable to decode " + component); Log.i("LL", "unable to decode " + component);
// pass, error in input array // pass, error in input array
} }
@ -194,7 +192,10 @@ public class IconPack {
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} finally { } 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); // File pages_dir = FileUtils.getPagesDir(Customize.this);
@ -227,55 +228,59 @@ public class IconPack {
File icon_dir = page.getAndCreateIconDir(); File icon_dir = page.getAndCreateIconDir();
icon_dir.mkdirs(); 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"); 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"); 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"); 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(); page.setModified();
} }
// update items custom icon // update items custom icon
int n = 0; int n = 0;
for(Item i : page.items) { for (Item i : page.items) {
if(item_id != Item.NO_ID && i.mId != item_id) { if (item_id != Item.NO_ID && i.mId != item_id) {
continue; continue;
} }
if(i.getClass() == Shortcut.class) { if (i.getClass() == Shortcut.class) {
Shortcut s = (Shortcut)i; Shortcut s = (Shortcut) i;
boolean icon_found = false; boolean icon_found = false;
ComponentName cn = s.getIntent().getComponent(); ComponentName cn = s.getIntent().getComponent();
if(cn != null) { if (cn != null) {
// try to get an id through the appfilter way // try to get an id through the appfilter way
Integer drawable_id = component_name_ids.get(cn.flattenToString()); 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) // 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 class_name = cn.getClassName();
String icon_name = class_name.replace('.', '_').toLowerCase(); String icon_name = class_name.replace('.', '_').toLowerCase();
drawable_id = icon_name_ids.get(icon_name); drawable_id = icon_name_ids.get(icon_name);
if(drawable_id == null) { if (drawable_id == null) {
int pos = class_name.lastIndexOf('.')+1; // if not found will produce 0 which is fine 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(); icon_name = (cn.getPackageName() + "_" + class_name.substring(pos)).replace('.', '_').toLowerCase();
drawable_id = icon_name_ids.get(icon_name); drawable_id = icon_name_ids.get(icon_name);
if(drawable_id == null) { if (drawable_id == null) {
icon_name = cn.getPackageName().replace('.', '_').toLowerCase(); icon_name = cn.getPackageName().replace('.', '_').toLowerCase();
drawable_id = icon_name_ids.get(icon_name); 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) // save the drawable using the target size (if less than the icon from the pack)
String default_icon_path = icon_dir+"/"+s.getId(); String default_icon_path = icon_dir + "/" + s.getId();
File custom_icon_file = new File(default_icon_path+"c"); File custom_icon_file = new File(default_icon_path + "c");
Drawable drawable = Utils.decodeDrawableResource(res, drawable_id.intValue()); Drawable drawable = Utils.decodeDrawableResource(res, drawable_id.intValue());
if(drawable != null) { if (drawable != null) {
BitmapFactory.Options opts = new BitmapFactory.Options(); BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true; opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(default_icon_path, opts); BitmapFactory.decodeFile(default_icon_path, opts);
@ -293,16 +298,16 @@ public class IconPack {
} }
} }
if(icon_found) { if (icon_found) {
int id = s.getId(); int id = s.getId();
ShortcutConfig sc = s.getShortcutConfig().clone(); ShortcutConfig sc = s.getShortcutConfig().clone();
sc.iconEffectScale = 1; sc.iconEffectScale = 1;
saveEmptyBitmap(sc.getIconBackFile(icon_dir, id)); saveEmptyBitmap(ShortcutConfig.getIconBackFile(icon_dir, id));
saveEmptyBitmap(sc.getIconOverFile(icon_dir, id)); saveEmptyBitmap(ShortcutConfig.getIconOverFile(icon_dir, id));
saveEmptyBitmap(sc.getIconMaskFile(icon_dir, id)); saveEmptyBitmap(ShortcutConfig.getIconMaskFile(icon_dir, id));
s.setShortcutConfig(sc); s.setShortcutConfig(sc);
} else if(icon_effect_back.size() > 1) { } else if (icon_effect_back.size() > 1) {
Bitmap bitmap = icon_effect_back.get((n++)%icon_effect_back.size()); Bitmap bitmap = icon_effect_back.get((n++) % icon_effect_back.size());
saveBitmapToFile(bitmap, ShortcutConfig.getIconBackFile(icon_dir, s.getId())); saveBitmapToFile(bitmap, ShortcutConfig.getIconBackFile(icon_dir, s.getId()));
s.modifyShortcutConfig().iconEffectScale = icon_effect_scale; s.modifyShortcutConfig().iconEffectScale = icon_effect_scale;
} }
@ -313,7 +318,7 @@ public class IconPack {
} }
private static void doApplyIconPackPostExecute(Page page, int item_id) { private static void doApplyIconPackPostExecute(Page page, int item_id) {
if(item_id == Item.NO_ID) { if (item_id == Item.NO_ID) {
page.save(); page.save();
page.reload(); page.reload();
} else { } else {
@ -321,7 +326,6 @@ public class IconPack {
} }
} }
private static void saveEmptyBitmap(File to) { private static void saveEmptyBitmap(File to) {
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
@ -333,7 +337,9 @@ public class IconPack {
} catch (IOException e) { } catch (IOException e) {
to.delete(); to.delete();
} finally { } 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); int id = res.getIdentifier(name, "drawable", package_name);
try { try {
Drawable d = res.getDrawable(id); Drawable d = res.getDrawable(id);
if(d instanceof BitmapDrawable) { if (d instanceof BitmapDrawable) {
return ((BitmapDrawable)d).getBitmap(); return ((BitmapDrawable) d).getBitmap();
} }
} catch(Resources.NotFoundException e) { } catch (Resources.NotFoundException e) {
// pass // pass
} }
return null; return null;
@ -355,10 +361,17 @@ public class IconPack {
try { try {
fos = new FileOutputStream(file); fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch(IOException e) { } catch (IOException e) {
file.delete(); file.delete();
} finally { } 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; import java.util.HashMap;
public class JsonLoader { public class JsonLoader {
/** Specialized for configuration objects, not a multi-purpose tool. */ /**
public static JSONObject toJSONObject(Object o, Object default_value) { * Specialized for configuration objects, not a multi-purpose tool.
JSONObject json_object=new JSONObject(); */
public static JSONObject toJSONObject(Object o, Object default_value) {
JSONObject json_object = new JSONObject();
toJSONObject(json_object, o, default_value); toJSONObject(json_object, o, default_value);
return json_object; return json_object;
} }
/** Specialized for configuration objects, not a multi-purpose tool. */ /**
public static void toJSONObject(JSONObject json_object, Object o, Object default_value) { * Specialized for configuration objects, not a multi-purpose tool.
for(Field f : o.getClass().getFields()) { */
if(Modifier.isFinal(f.getModifiers())) continue; 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) { if (default_value != null) {
try { try {
Object f_o = f.get(o); Object f_o = f.get(o);
Object f_do = f.get(default_value); Object f_do = f.get(default_value);
if(f_o==null && f_do==null) continue; if (f_o == null && f_do == null) continue;
if(f_o!=null && f_o.equals(f_do)) continue; if (f_o != null && f_o.equals(f_do)) continue;
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
String name=f.getName(); String name = f.getName();
try { try {
Class<?> cls=f.getType(); Class<?> cls = f.getType();
if(cls==boolean.class) { if (cls == boolean.class) {
json_object.put(name, f.getBoolean(o)); json_object.put(name, f.getBoolean(o));
} else if(cls==int.class) { } else if (cls == int.class) {
json_object.put(name, f.getInt(o)); json_object.put(name, f.getInt(o));
} else if(cls==long.class) { } else if (cls == long.class) {
json_object.put(name, f.getLong(o)); json_object.put(name, f.getLong(o));
} else if(cls==int[].class) { } else if (cls == int[].class) {
int[] ai=(int[])f.get(o); int[] ai = (int[]) f.get(o);
if(ai!=null) { if (ai != null) {
JSONArray jai=new JSONArray(); JSONArray jai = new JSONArray();
for(int i : ai) { for (int i : ai) {
jai.put(i); jai.put(i);
} }
json_object.put(name, jai); json_object.put(name, jai);
} }
} else if(cls==float.class) { } else if (cls == float.class) {
json_object.put(name, (double)f.getFloat(o)); json_object.put(name, f.getFloat(o));
} else if(cls==String.class) { } else if (cls == String.class) {
json_object.put(name, (String)f.get(o)); json_object.put(name, f.get(o));
} else if(cls==String[].class) { } else if (cls == String[].class) {
String[] as=(String[])f.get(o); String[] as = (String[]) f.get(o);
if(as!=null) { if (as != null) {
JSONArray jas=new JSONArray(); JSONArray jas = new JSONArray();
for(String s : as) { for (String s : as) {
jas.put(s); jas.put(s);
} }
json_object.put(name, jas); json_object.put(name, jas);
} }
} else if(cls==EventAction.class) { } else if (cls == EventAction.class) {
EventAction ea = (EventAction) f.get(o); EventAction ea = (EventAction) f.get(o);
if (ea != null && ea.action != GlobalConfig.UNSET) { if (ea != null && ea.action != GlobalConfig.UNSET) {
JSONObject j_ea = new JSONObject(); JSONObject j_ea = new JSONObject();
j_ea.put("a", ea.action); j_ea.put("a", ea.action);
j_ea.put("d", ea.data); j_ea.put("d", ea.data);
if(ea.next != null) { if (ea.next != null) {
j_ea.put("n", toJSONObject(ea.next, null)); j_ea.put("n", toJSONObject(ea.next, null));
} }
json_object.put(name, j_ea); json_object.put(name, j_ea);
} }
} else if(cls== Binding[].class) { } else if (cls == Binding[].class) {
Binding[] bindings=(Binding[])f.get(o); Binding[] bindings = (Binding[]) f.get(o);
if(bindings!=null) { if (bindings != null) {
JSONArray jbindings=new JSONArray(); JSONArray jbindings = new JSONArray();
for(Binding binding : bindings) { for (Binding binding : bindings) {
JSONObject j = new JSONObject(); JSONObject j = new JSONObject();
j.put("t", binding.target); j.put("t", binding.target);
j.put("f", binding.formula); j.put("f", binding.formula);
@ -97,86 +101,82 @@ public class JsonLoader {
} }
json_object.put(name, jbindings); json_object.put(name, jbindings);
} }
} else if(cls==HashMap.class) { } else if (cls == HashMap.class) {
HashMap m = (HashMap) f.get(o); HashMap m = (HashMap) f.get(o);
if(m != null) { if (m != null) {
json_object.put(name, new JSONObject((HashMap)f.get(o))); 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()); json_object.put(name, f.get(o).toString());
} }
} catch(IllegalAccessException e) { } catch (IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
public void loadFieldsFromJSONObject(JSONObject json, Object d) {
loadFieldsFromJSONObject(this, json, d);
} }
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({"rawtypes", "unchecked"})
public static void loadFieldsFromJSONObject(Object thiz, JSONObject json, Object d) { public static void loadFieldsFromJSONObject(Object thiz, JSONObject json, Object d) {
if(d == null) { if (d == null) {
d = thiz; d = thiz;
} }
for(Field f : thiz.getClass().getFields()) { for (Field f : thiz.getClass().getFields()) {
if(Modifier.isFinal(f.getModifiers())) continue; if (Modifier.isFinal(f.getModifiers())) continue;
String name=f.getName(); String name = f.getName();
try { try {
Class<?> cls=f.getType(); Class<?> cls = f.getType();
if(cls==boolean.class) { if (cls == boolean.class) {
f.setBoolean(thiz, json.optBoolean(name, f.getBoolean(d))); f.setBoolean(thiz, json.optBoolean(name, f.getBoolean(d)));
} else if(cls==int.class) { } else if (cls == int.class) {
f.setInt(thiz, json.optInt(name, f.getInt(d))); f.setInt(thiz, json.optInt(name, f.getInt(d)));
} else if(cls==int[].class) { } 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) {
JSONArray a = json.optJSONArray(name); JSONArray a = json.optJSONArray(name);
if(a==null) { if (a == null) {
f.set(thiz, null); f.set(thiz, null);
} else { } else {
int n=a.length(); int n = a.length();
String[] as=new String[n]; int[] ai = new int[n];
for(int i=0; i<n; i++) { 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); as[i] = a.getString(i);
} }
f.set(thiz, as); f.set(thiz, as);
} }
} else if(cls.isEnum()) { } else if (cls.isEnum()) {
String enum_string=json.optString(name, null); String enum_string = json.optString(name, null);
if(enum_string!=null) { if (enum_string != null) {
f.set(thiz, Enum.valueOf((Class<Enum>)cls, enum_string)); f.set(thiz, Enum.valueOf((Class<Enum>) cls, enum_string));
} else { } else {
f.set(thiz, f.get(d)); f.set(thiz, f.get(d));
} }
} else if(cls==EventAction.class) { } else if (cls == EventAction.class) {
EventAction ea; EventAction ea;
if (json.has(name)) { if (json.has(name)) {
try { try {
JSONObject j_ea = json.getJSONObject(name); JSONObject j_ea = json.getJSONObject(name);
JSONObject n = j_ea.optJSONObject("n"); JSONObject n = j_ea.optJSONObject("n");
EventAction next = null; EventAction next = null;
if(n != null) { if (n != null) {
next = new EventAction(); next = new EventAction();
loadFieldsFromJSONObject(next, n, null); loadFieldsFromJSONObject(next, n, null);
} }
@ -191,14 +191,14 @@ public class JsonLoader {
ea = d_ea; ea = d_ea;
} }
f.set(thiz, ea); f.set(thiz, ea);
} else if(cls== Binding[].class) { } else if (cls == Binding[].class) {
JSONArray a = json.optJSONArray(name); JSONArray a = json.optJSONArray(name);
if(a==null) { if (a == null) {
f.set(thiz, null); f.set(thiz, null);
} else { } else {
int n=a.length(); int n = a.length();
Binding[] bindings; Binding[] bindings;
if(n==0) { if (n == 0) {
bindings = null; bindings = null;
} else { } else {
bindings = new Binding[n]; bindings = new Binding[n];
@ -210,37 +210,29 @@ public class JsonLoader {
} }
f.set(thiz, bindings); f.set(thiz, bindings);
} }
} else if(cls==HashMap.class) { } else if (cls == HashMap.class) {
JSONObject o = json.optJSONObject(name); JSONObject o = json.optJSONObject(name);
if(o != null) { if (o != null) {
f.set(thiz, Utils.jsonObjectToHashMap(o)); f.set(thiz, Utils.jsonObjectToHashMap(o));
} else { } else {
f.set(thiz, f.get(d)); f.set(thiz, f.get(d));
} }
} else if(cls.getSuperclass()==JsonLoader.class) { } else if (cls.getSuperclass() == JsonLoader.class) {
JsonLoader j=(JsonLoader)cls.newInstance(); JsonLoader j = (JsonLoader) cls.newInstance();
JSONObject o2=json.optJSONObject(name); JSONObject o2 = json.optJSONObject(name);
if(o2==null) { if (o2 == null) {
o2=new JSONObject(); o2 = new JSONObject();
} }
j.loadFieldsFromJSONObject(o2, f.get(d)); j.loadFieldsFromJSONObject(o2, f.get(d));
f.set(thiz, j); f.set(thiz, j);
} }
} catch(Exception e) { } catch (Exception e) {
Log.i("LL", "bad field "+name); Log.i("LL", "bad field " + name);
// pass // pass
// e.printStackTrace(); // 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) { public static <T extends JsonLoader> T readObject(Class<T> cls, File from) {
T instance; T instance;
@ -252,7 +244,7 @@ public class JsonLoader {
} }
JSONObject json = FileUtils.readJSONObjectFromFile(from); JSONObject json = FileUtils.readJSONObjectFromFile(from);
if(json != null) { if (json != null) {
instance.loadFieldsFromJSONObject(json, instance); 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 @Override
public String toString() { public String toString() {
return JsonLoader.toJSONObject(this, null).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.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Matrix;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import net.pierrox.lightning_launcher.configuration.*;
import net.pierrox.lightning_launcher.BuildConfig; 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.engine.LightningEngine;
import net.pierrox.lightning_launcher.views.ItemLayout; import net.pierrox.lightning_launcher.views.ItemLayout;
import net.pierrox.lightning_launcher.views.item.ItemView; 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 // home pages: 0->98, app app_drawer:99, folders: 100->N
// these ids are stored as string, even if only numeric values today // these ids are stored as string, even if only numeric values today
public static final int NONE =-1; public static final int NONE = -1;
public static final int FIRST_DASHBOARD_PAGE=0; public static final int FIRST_DASHBOARD_PAGE = 0;
public static final int LAST_DASHBOARD_PAGE=98; public static final int LAST_DASHBOARD_PAGE = 98;
public static final int APP_DRAWER_PAGE=99; public static final int APP_DRAWER_PAGE = 99;
public static final int FIRST_FOLDER_PAGE=100; public static final int FIRST_FOLDER_PAGE = 100;
public static final int LAST_FOLDER_PAGE=999; public static final int LAST_FOLDER_PAGE = 999;
public static final int USER_MENU_PAGE=0x7fff; public static final int USER_MENU_PAGE = 0x7fff;
public static final int MERGED_APP_DRAWER_PAGE=0x7ffe; public static final int MERGED_APP_DRAWER_PAGE = 0x7ffe;
private static final String _backgroundColor = "backgroundColor";
private static final String _backgroundWallpaper = "backgroundWallpaper";
public interface PageListener extends Item.OnItemEventListener{ private static final String _backgroundWallpaperScroll = "backgroundWallpaperScroll";
public void onPageLoaded(Page page); private static final String _backgroundWallpaperTintColor = "backgroundWallpaperTintColor";
public void onPageRemoved(Page page); private static final String _backgroundWallpaperWidth = "backgroundWallpaperWidth";
public void onPagePaused(Page page); private static final String _backgroundWallpaperHeight = "backgroundWallpaperHeight";
public void onPageResumed(Page page); private static final String _gridColumnMode = "gridColumnMode";
private static final String _gridColumnNum = "gridColumnNum";
public void onPageModified(Page page); private static final String _gridColumnSize = "gridColumnSize";
private static final String _gridRowMode = "gridRowMode";
// TODO move this to engine, this is not a page specific data private static final String _gridRowNum = "gridRowNum";
public void onPageEditModeEntered(Page page); private static final String _gridRowSize = "gridRowSize";
public void onPageEditModeLeaved(Page page); private static final String _layoutMode = "layoutMode";
private static final String _transpBarOverlap = "transpBarOverlap";
public void onPageItemLoaded(Item item); private static final String _statusBarTransparent = "statusBarTransparent";
public void onPageItemDestroyed(Item item); private static final String _navigationBarTransparent = "navigationBarTransparent";
public void onPageItemAdded(Item item); private static final String _wrap = "wrap";
public void onPageItemBeforeRemove(Item item); private final File mIconDir;
public void onPageItemRemoved(Page page, Item item); public int id;
public void onPageItemChanged(Page page, Item item); public PageConfig config;
public ArrayList<Item> items;
public void onPageItemZIndexChanged(Page page, int old_index, int new_index); protected PageListener mListener;
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) { }
}
// TODO both fields are the same // TODO both fields are the same
private LightningEngine mLightningEngine; private LightningEngine mLightningEngine;
protected PageListener mListener; private boolean modified;
private File mIconDir;
private boolean modified;
public int id;
public PageConfig config;
public ArrayList<Item> items;
private float mCurrentViewCellWidth; private float mCurrentViewCellWidth;
private float mCurrentViewCellHeight; private float mCurrentViewCellHeight;
private int mResumeCount; private int mResumeCount;
private boolean mIsBeingRemoved; // prevent endless recursion
public Page(LightningEngine lightningEngine, int id) { public Page(LightningEngine lightningEngine, int id) {
mLightningEngine = lightningEngine; mLightningEngine = lightningEngine;
@ -112,42 +79,110 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
mIconDir = getIconDir(mLightningEngine.getBaseDir(), id); mIconDir = getIconDir(mLightningEngine.getBaseDir(), id);
} }
@Override public static boolean isDashboard(int p) {
public String toString() { return p >= FIRST_DASHBOARD_PAGE && p <= LAST_DASHBOARD_PAGE;
return "Page:"+id+" ("+hashCode()+")";
} }
public static boolean isDashboard(int p) { public static boolean isFolder(int p) {
return p>=FIRST_DASHBOARD_PAGE && p<=LAST_DASHBOARD_PAGE; 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() { public boolean isDashboard() {
return isDashboard(id); 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() { public boolean isFolder() {
return isFolder(id); return isFolder(id);
} }
public void setEngine(LightningEngine lightningEngine) {
mLightningEngine = lightningEngine;
}
public LightningEngine getEngine() { public LightningEngine getEngine() {
return mLightningEngine; return mLightningEngine;
} }
public void setEngine(LightningEngine lightningEngine) {
mLightningEngine = lightningEngine;
}
public void pause() { public void pause() {
mResumeCount--; mResumeCount--;
// Log.i("XXX", "pause page "+id+" "+mResumeCount); // Log.i("XXX", "pause page "+id+" "+mResumeCount);
if(mResumeCount == 0) { if (mResumeCount == 0) {
// Log.i("XXX", "pause page "+id); // Log.i("XXX", "pause page "+id);
for(Item item : items) { for (Item item : items) {
item.pause(); item.pause();
} }
mListener.onPagePaused(this); mListener.onPagePaused(this);
@ -157,7 +192,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void resume() { public void resume() {
mResumeCount++; mResumeCount++;
// Log.i("XXX", "resume page "+id+" "+mResumeCount); // Log.i("XXX", "resume page "+id+" "+mResumeCount);
if(mResumeCount == 1) { if (mResumeCount == 1) {
// Log.i("XXX", "resume page "+id); // Log.i("XXX", "resume page "+id);
for (Item item : items) { for (Item item : items) {
item.resume(); item.resume();
@ -181,16 +216,16 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
loadConfig(); 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 // 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); Page home = mLightningEngine.getOrLoadPage(FIRST_DASHBOARD_PAGE);
config.defaultFolderConfig=home.config.defaultFolderConfig; config.defaultFolderConfig = home.config.defaultFolderConfig;
} }
loadItems(); loadItems();
if(BuildConfig.IS_BETA) { 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()); 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() { public void destroy() {
// Log.i("XXX", "destroy page "+page); // Log.i("XXX", "destroy page "+page);
if(mResumeCount > 0) { if (mResumeCount > 0) {
pause(); pause();
mResumeCount = 0; mResumeCount = 0;
} }
for(Item item : items) { for (Item item : items) {
mListener.onPageItemDestroyed(item); mListener.onPageItemDestroyed(item);
item.onDestroy(); item.onDestroy();
} }
} }
private boolean mIsBeingRemoved; // prevent endless recursion
public void remove() { public void remove() {
if(!mIsBeingRemoved) { if (!mIsBeingRemoved) {
mIsBeingRemoved = true; mIsBeingRemoved = true;
for (Item item : items) { for (Item item : items) {
@ -241,33 +275,25 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
} }
public void save() { public void save() {
if(modified && id != Page.NONE) { if (modified && id != Page.NONE) {
saveConfig(); saveConfig();
saveItems(); 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() { public int findFreeItemId() {
// linked with Utils.getPageForItemId // linked with Utils.getPageForItemId
int max=0; int max = 0;
for(Item i : items) { for (Item i : items) {
if(i.getId()>max) max=i.getId(); if (i.getId() > max) max = i.getId();
} }
return composeItemId(id, max+1); return composeItemId(id, max + 1);
} }
public Item findItemById(int id) { public Item findItemById(int id) {
for(Item i : items) { for (Item i : items) {
if(i.getId()==id) return i; if (i.getId() == id) return i;
} }
return null; return null;
} }
@ -295,75 +321,9 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public File getIconDir() { public File getIconDir() {
return mIconDir; return mIconDir;
} }
public File getAndCreateIconDir() { public File getAndCreateIconDir() {
return getAndCreateIconDir(mLightningEngine.getBaseDir(), id); 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;
} }
@Override @Override
@ -371,6 +331,11 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
return config.defaultItemConfig; return config.defaultItemConfig;
} }
@Override
public void setItemConfig(ItemConfig c) {
config.defaultItemConfig = c;
}
@Override @Override
public ItemConfig modifyItemConfig() { public ItemConfig modifyItemConfig() {
return config.defaultItemConfig; return config.defaultItemConfig;
@ -406,7 +371,6 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
return config.defaultFolderConfig; return config.defaultFolderConfig;
} }
@Override @Override
public void onItemPaused(Item item) { public void onItemPaused(Item item) {
mListener.onItemPaused(item); mListener.onItemPaused(item);
@ -454,7 +418,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
@Override @Override
public void onFolderPageIdChanged(Folder folder, int oldPageId) { public void onFolderPageIdChanged(Folder folder, int oldPageId) {
if(items.contains(folder)) { if (items.contains(folder)) {
mListener.onFolderPageIdChanged(folder, oldPageId); mListener.onFolderPageIdChanged(folder, oldPageId);
} }
} }
@ -466,7 +430,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void setItemZIndex(Item item, int new_index) { public void setItemZIndex(Item item, int new_index) {
int old_index = items.indexOf(item); 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.remove(old_index);
items.add(new_index, item); items.add(new_index, item);
@ -481,14 +445,14 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
public void addItem(Item item, Integer index) { public void addItem(Item item, Integer index) {
modified = true; modified = true;
if(index == null) { if (index == null) {
items.add(item); items.add(item);
} else { } else {
items.add(index, item); items.add(index, item);
} }
mListener.onPageItemAdded(item); mListener.onPageItemAdded(item);
if(mResumeCount > 0) { if (mResumeCount > 0) {
item.resume(); item.resume();
} }
} }
@ -497,13 +461,13 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
mListener.onPageItemBeforeRemove(item); mListener.onPageItemBeforeRemove(item);
modified = true; modified = true;
if(mResumeCount > 0) item.pause(); if (mResumeCount > 0) item.pause();
item.onDestroy(); item.onDestroy();
item.onRemove(keepResources); item.onRemove(keepResources);
items.remove(item); items.remove(item);
ArrayList<File> icons = new ArrayList<>(); ArrayList<File> icons = new ArrayList<>();
item.getIconFiles(getIconDir(), icons); item.getIconFiles(getIconDir(), icons);
for(File f : icons) { for (File f : icons) {
f.delete(); f.delete();
} }
mListener.onPageItemRemoved(this, item); mListener.onPageItemRemoved(this, item);
@ -520,19 +484,19 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
mListener.onPageItemChanged(this, item); mListener.onPageItemChanged(this, item);
if(mResumeCount > 0) { if (mResumeCount > 0) {
item.resume(); item.resume();
} }
} }
public void notifyItemChanged(Item item) { public void notifyItemChanged(Item item) {
modified = true; modified = true;
if(mResumeCount > 0) item.pause(); if (mResumeCount > 0) item.pause();
item.onDestroy(); item.onDestroy();
item.onCreate(); item.onCreate();
mListener.onPageItemChanged(this, item); mListener.onPageItemChanged(this, item);
if(mResumeCount > 0) { if (mResumeCount > 0) {
item.resume(); item.resume();
} }
} }
@ -547,66 +511,48 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
} }
public float getCurrentViewCellWidth() { public float getCurrentViewCellWidth() {
return mCurrentViewCellWidth==0 ? Utils.getStandardIconSize() : mCurrentViewCellWidth; return mCurrentViewCellWidth == 0 ? Utils.getStandardIconSize() : mCurrentViewCellWidth;
} }
public float getCurrentViewCellHeight() { public float getCurrentViewCellHeight() {
return mCurrentViewCellHeight==0 ? Utils.getStandardIconSize() : mCurrentViewCellHeight; return mCurrentViewCellHeight == 0 ? Utils.getStandardIconSize() : mCurrentViewCellHeight;
} }
public void reload() { public void reload() {
int count = mResumeCount; int count = mResumeCount;
destroy(); destroy();
create(); create();
if(count > 0) { if (count > 0) {
resume(); resume();
mResumeCount = count; 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() { private void loadConfig() {
File json_file = getPageConfigFile(); File json_file = getPageConfigFile();
JSONObject json=FileUtils.readJSONObjectFromFile(json_file); JSONObject json = FileUtils.readJSONObjectFromFile(json_file);
if(json==null) { if (json == null) {
json=new JSONObject(); json = new JSONObject();
} }
PageConfig c=new PageConfig(); PageConfig c = new PageConfig();
c.applyDefaultFolderConfig(); c.applyDefaultFolderConfig();
// for low dpi devices, use icon filter by default // for low dpi devices, use icon filter by default
if(Utils.getStandardIconSize()==36) { if (Utils.getStandardIconSize() == 36) {
c.defaultShortcutConfig.iconFilter=true; c.defaultShortcutConfig.iconFilter = true;
} }
c.loadFieldsFromJSONObject(json, c); c.loadFieldsFromJSONObject(json, c);
File icon_dir=getIconDir(); File icon_dir = getIconDir();
c.defaultItemConfig.loadAssociatedIcons(icon_dir, Item.NO_ID); c.defaultItemConfig.loadAssociatedIcons(icon_dir, Item.NO_ID);
c.defaultShortcutConfig.loadAssociatedIcons(icon_dir, Item.NO_ID); c.defaultShortcutConfig.loadAssociatedIcons(icon_dir, Item.NO_ID);
c.defaultFolderConfig.loadAssociatedIcons(icon_dir, Item.NO_ID); c.defaultFolderConfig.loadAssociatedIcons(icon_dir, Item.NO_ID);
// legacy with < 90 // 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); int backgroundColor = json.optInt(_backgroundColor, 0xff000000);
boolean backgroundWallpaper = json.optBoolean(_backgroundWallpaper, true); boolean backgroundWallpaper = json.optBoolean(_backgroundWallpaper, true);
boolean backgroundWallpaperScroll = json.optBoolean(_backgroundWallpaperScroll, false); 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 backgroundWallpaperWidth = json.optInt(_backgroundWallpaperWidth, 0);
int backgroundWallpaperHeight = json.optInt(_backgroundWallpaperHeight, 0); int backgroundWallpaperHeight = json.optInt(_backgroundWallpaperHeight, 0);
if(backgroundWallpaper) { if (backgroundWallpaper) {
c.bgColor = backgroundWallpaperTintColor; c.bgColor = backgroundWallpaperTintColor;
} else { } else {
c.bgColor = backgroundColor; c.bgColor = backgroundColor;
@ -624,7 +570,7 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
c.bgSystemWPHeight = backgroundWallpaperHeight; 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.gridPColumnMode = c.gridLColumnMode = PageConfig.SizeMode.valueOf(json.optString(_gridColumnMode, PageConfig.SizeMode.NUM.name()));
c.gridPColumnNum = c.gridLColumnNum = json.optInt(_gridColumnNum, 5); c.gridPColumnNum = c.gridLColumnNum = json.optInt(_gridColumnNum, 5);
c.gridPColumnSize = c.gridLColumnSize = json.optInt(_gridColumnSize, 100); c.gridPColumnSize = c.gridLColumnSize = json.optInt(_gridColumnSize, 100);
@ -634,29 +580,29 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
} }
// legacy with < 135 // legacy with < 135
if(json.has(_layoutMode)) { if (json.has(_layoutMode)) {
c.newOnGrid = c.defaultItemConfig.onGrid = "GRID".equals(json.optString(_layoutMode)); c.newOnGrid = c.defaultItemConfig.onGrid = "GRID".equals(json.optString(_layoutMode));
} }
// legacy with < 208 // legacy with < 208
boolean has_statusBarTransparent = true; boolean has_statusBarTransparent = true;
if(json.has(_statusBarTransparent)) { if (json.has(_statusBarTransparent)) {
has_statusBarTransparent = json.optBoolean(_statusBarTransparent); has_statusBarTransparent = json.optBoolean(_statusBarTransparent);
c.statusBarColor = has_statusBarTransparent ? 0 : Color.BLACK; c.statusBarColor = has_statusBarTransparent ? 0 : Color.BLACK;
} }
boolean has_navigationBarTransparent = true; boolean has_navigationBarTransparent = true;
if(json.has(_navigationBarTransparent)) { if (json.has(_navigationBarTransparent)) {
has_navigationBarTransparent = json.optBoolean(_navigationBarTransparent); has_navigationBarTransparent = json.optBoolean(_navigationBarTransparent);
c.navigationBarColor = has_navigationBarTransparent ? 0 : Color.BLACK; c.navigationBarColor = has_navigationBarTransparent ? 0 : Color.BLACK;
} }
if(json.has(_transpBarOverlap)) { if (json.has(_transpBarOverlap)) {
boolean overlap = json.optBoolean(_transpBarOverlap); boolean overlap = json.optBoolean(_transpBarOverlap);
c.statusBarOverlap = overlap && has_statusBarTransparent; c.statusBarOverlap = overlap && has_statusBarTransparent;
c.navigationBarOverlap = overlap && has_navigationBarTransparent; c.navigationBarOverlap = overlap && has_navigationBarTransparent;
} }
if(json.has(_wrap)) { if (json.has(_wrap)) {
boolean wrap = json.optBoolean(_wrap); boolean wrap = json.optBoolean(_wrap);
c.wrapX = wrap; c.wrapX = wrap;
c.wrapY = wrap; c.wrapY = wrap;
@ -668,19 +614,19 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
private void loadItems() { 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; long t1 = BuildConfig.IS_BETA ? SystemClock.uptimeMillis() : 0;
if(json_data!=null) { if (json_data != null) {
try { try {
JSONArray json_items=json_data.getJSONArray(JsonFields.ITEMS); JSONArray json_items = json_data.getJSONArray(JsonFields.ITEMS);
int l=json_items.length(); int l = json_items.length();
items=new ArrayList<>(l); items = new ArrayList<>(l);
for(int i=0; i<l; i++) { for (int i = 0; i < l; i++) {
JSONObject o=json_items.getJSONObject(i); JSONObject o = json_items.getJSONObject(i);
Item item=Item.loadItemFromJSONObject(this, o); Item item = Item.loadItemFromJSONObject(this, o);
if(item!=null) { if (item != null) {
items.add(item); items.add(item);
mListener.onPageItemLoaded(item); mListener.onPageItemLoaded(item);
} }
@ -689,11 +635,11 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
e.printStackTrace(); e.printStackTrace();
} }
} }
if(items == null) { if (items == null) {
items=new ArrayList<>(); items = new ArrayList<>();
} }
if(BuildConfig.IS_BETA) { if (BuildConfig.IS_BETA) {
Log.i("LL", "loadItems for page "+id+" in "+(SystemClock.uptimeMillis()-t1)); 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(); //long t1= SystemClock.uptimeMillis();
try { try {
JSONArray json_items=new JSONArray(); JSONArray json_items = new JSONArray();
getAndCreateIconDir(); getAndCreateIconDir();
for(Item item : items) { for (Item item : items) {
JSONObject json_item=item.toJSONObject(); JSONObject json_item = item.toJSONObject();
json_items.put(json_item); json_items.put(json_item);
if(item.getClass() == Widget.class) { if (item.getClass() == Widget.class) {
ItemView v = Utils.findItemViewInAppScreens(item); ItemView v = Utils.findItemViewInAppScreens(item);
if(v != null && ((WidgetView)v).isGood()) { if (v != null && ((WidgetView) v).isGood()) {
OutputStream os = null; OutputStream os = null;
try { try {
os = new FileOutputStream(item.getDefaultIconFile()); os = new FileOutputStream(item.getDefaultIconFile());
@ -748,22 +694,160 @@ public class Page implements Item.OnItemEventListener, ItemConfigStylable, Short
Canvas canvas = new Canvas(b); Canvas canvas = new Canvas(b);
v.draw(canvas); v.draw(canvas);
b.compress(Bitmap.CompressFormat.PNG, 100, os); b.compress(Bitmap.CompressFormat.PNG, 100, os);
} catch(Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} finally { } 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); data.put(JsonFields.ITEMS, json_items);
FileUtils.saveStringToFile(data.toString(), getItemsFile()); FileUtils.saveStringToFile(data.toString(), getItemsFile());
} catch(Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
//Log.i("LL", "saveItems in "+(SystemClock.uptimeMillis()-t1)); //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; import java.util.ArrayList;
public class PageProcessor { public class PageProcessor {
private ComponentName drawer_from; private final ComponentName drawer_from;
private ComponentName drawer_to; private final ComponentName drawer_to;
private String pkg_name_from; private final String pkg_name_from;
private String pkg_name_to; private final String pkg_name_to;
private boolean do_scale; private boolean do_scale;
private float sx; private float sx;
@ -39,7 +39,7 @@ public class PageProcessor {
// private int to_screen_width; // private int to_screen_width;
// private int to_screen_height; // private int to_screen_height;
// private int to_sb_height; // private int to_sb_height;
private boolean enforce_holo; private boolean enforce_holo;
private boolean process_global_config; private boolean process_global_config;
@ -47,8 +47,8 @@ public class PageProcessor {
private SparseIntArray translated_script_ids; private SparseIntArray translated_script_ids;
public PageProcessor() { public PageProcessor() {
ComponentName ll_app_drawer = new ComponentName(LLApp.LL_PKG_NAME, LLApp.LL_PKG_NAME+".activities.AppDrawer"); 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 llx_app_drawer = new ComponentName(LLApp.LLX_PKG_NAME, LLApp.LLX_PKG_NAME + ".activities.AppDrawerX");
String my_pkg_name = LLApp.get().getPackageName(); String my_pkg_name = LLApp.get().getPackageName();
boolean is_llx = my_pkg_name.equals(LLApp.LLX_PKG_NAME); 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_width = to_screen_width;
// this.to_screen_height = to_screen_height; // this.to_screen_height = to_screen_height;
// this.to_sb_height = to_sb_height; // this.to_sb_height = to_sb_height;
if(to_screen_width != 0) { if (to_screen_width != 0) {
do_scale = true; do_scale = true;
sx = to_screen_width / (float)from_screen_width; sx = to_screen_width / (float) from_screen_width;
sy = (to_screen_height - to_sb_height) / (float)(from_screen_height - from_sb_height); sy = (to_screen_height - to_sb_height) / (float) (from_screen_height - from_sb_height);
} }
} }
public void setEnforceHoloSelection(boolean enforce_holo) { public void setEnforceHoloSelection(boolean enforce_holo) {
this.enforce_holo = enforce_holo; this.enforce_holo = enforce_holo;
} }
public void postProcessPages(ArrayList<Page> pages) { public void postProcessPages(ArrayList<Page> pages) {
for(Page page : pages) { for (Page page : pages) {
postProcessPage(page); postProcessPage(page);
page.setModified(); page.setModified();
page.save(); 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() // TODO see whether this can be replaced with direct access of engine.getGlobalConfigFile()
File base_dir = pages.get(0).getEngine().getBaseDir(); File base_dir = pages.get(0).getEngine().getBaseDir();
File global_config_file = FileUtils.getGlobalConfigFile(base_dir); 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 // check that the home page is valid, otherwise fix it
boolean valid = false; boolean valid = false;
for(Page page : pages) { for (Page page : pages) {
if(page.id == gc.homeScreen) { if (page.id == gc.homeScreen) {
valid = true; valid = true;
break; break;
} }
} }
if(!valid) { if (!valid) {
// use the first dashboard page // use the first dashboard page
if(pages.size() > 0) { if (pages.size() > 0) {
for(Page page : pages) { for (Page page : pages) {
int id = page.id; int id = page.id;
if(Page.isDashboard(id)) { if (Page.isDashboard(id)) {
gc.homeScreen = id; gc.homeScreen = id;
break; break;
} }
@ -163,7 +163,7 @@ public class PageProcessor {
} }
} }
} }
public void copyAndTranslatePage(Page pageFrom, LightningEngine engineTo, boolean keepAppWidgetId) { public void copyAndTranslatePage(Page pageFrom, LightningEngine engineTo, boolean keepAppWidgetId) {
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
@ -173,7 +173,7 @@ public class PageProcessor {
File baseDirFrom = pageFrom.getEngine().getBaseDir(); File baseDirFrom = pageFrom.getEngine().getBaseDir();
File baseDirTo = engineTo.getBaseDir(); File baseDirTo = engineTo.getBaseDir();
Page p = engineTo.getPageManager().getPage(new_page_id); 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"); throw new RuntimeException("Attempt to overwrite an existing page during import");
} else { } else {
// make sure that the place is clean // make sure that the place is clean
@ -190,7 +190,7 @@ public class PageProcessor {
pageTo.config.copyFrom(pageFrom.config); pageTo.config.copyFrom(pageFrom.config);
pageTo.items = new ArrayList<>(pageFrom.items.size()); 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 old_item_id = old_item.getId();
int new_item_id = Page.composeItemId(new_page_id, Page.getBaseItemId(old_item_id)); int new_item_id = Page.composeItemId(new_page_id, Page.getBaseItemId(old_item_id));
@ -200,7 +200,7 @@ public class PageProcessor {
try { try {
JSONObject json = old_item.toJSONObject(); JSONObject json = old_item.toJSONObject();
json.put(JsonFields.ITEM_ID, new_item_id); 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); json.put(JsonFields.WIDGET_APP_WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
} }
new_item = Item.loadItemFromJSONObject(pageTo, json); new_item = Item.loadItemFromJSONObject(pageTo, json);
@ -209,8 +209,8 @@ public class PageProcessor {
new_item = null; new_item = null;
} }
if(new_item instanceof Folder) { if (new_item instanceof Folder) {
Folder f = (Folder)new_item; Folder f = (Folder) new_item;
f.setFolderPageId(translated_page_ids.get(f.getFolderPageId())); f.setFolderPageId(translated_page_ids.get(f.getFolderPageId()));
} }
@ -237,14 +237,14 @@ public class PageProcessor {
PageConfig c = page.config; PageConfig c = page.config;
if(do_scale) { if (do_scale) {
c.gridLColumnSize *= sx; c.gridLColumnSize *= sx;
c.gridPColumnSize *= sx; c.gridPColumnSize *= sx;
c.gridLRowSize *= sy; c.gridLRowSize *= sy;
c.gridPRowSize *= 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; c.defaultItemConfig.selectionEffect = ItemConfig.SelectionEffect.HOLO;
} }
@ -290,7 +290,7 @@ public class PageProcessor {
postProcessEventAction(pic.menu); postProcessEventAction(pic.menu);
FolderConfig pfc = c.defaultFolderConfig; 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.wX *= sx;
pfc.wY *= sy; pfc.wY *= sy;
pfc.wW *= sx; pfc.wW *= sx;
@ -298,9 +298,9 @@ public class PageProcessor {
} }
ArrayList<Item> items = page.items; ArrayList<Item> items = page.items;
for(Item i : items) { for (Item i : items) {
ItemConfig ic = i.getItemConfig(); ItemConfig ic = i.getItemConfig();
if(ic != pic) { if (ic != pic) {
postProcessEventAction(ic.tap); postProcessEventAction(ic.tap);
postProcessEventAction(ic.longTap); postProcessEventAction(ic.longTap);
postProcessEventAction(ic.swipeLeft); postProcessEventAction(ic.swipeLeft);
@ -313,8 +313,8 @@ public class PageProcessor {
postProcessEventAction(ic.menu); postProcessEventAction(ic.menu);
} }
if(!ic.onGrid && do_scale) { if (!ic.onGrid && do_scale) {
i.setViewWidth((int)(i.getViewWidth() * sx)); i.setViewWidth((int) (i.getViewWidth() * sx));
i.setViewHeight((int) (i.getViewHeight() * sy)); i.setViewHeight((int) (i.getViewHeight() * sy));
Matrix m = i.getTransform(); Matrix m = i.getTransform();
m.getValues(matrix_values); m.getValues(matrix_values);
@ -325,24 +325,24 @@ public class PageProcessor {
} }
Class<?> cls = i.getClass(); Class<?> cls = i.getClass();
if(cls == StopPoint.class) { if (cls == StopPoint.class) {
postProcessEventAction(((StopPoint)i).getReachedAction()); postProcessEventAction(((StopPoint) i).getReachedAction());
} else if(cls == CustomView.class) { } else if (cls == CustomView.class) {
CustomView customView = (CustomView) i; CustomView customView = (CustomView) i;
String newIdData = translateScriptAction(customView.onCreate); String newIdData = translateScriptAction(customView.onCreate);
if(newIdData != null) customView.onCreate = newIdData; if (newIdData != null) customView.onCreate = newIdData;
newIdData = translateScriptAction(customView.onDestroy); 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) { if (cls == Shortcut.class && page.id != Page.APP_DRAWER_PAGE) {
Shortcut s = (Shortcut)i; Shortcut s = (Shortcut) i;
Intent intent = s.getIntent(); Intent intent = s.getIntent();
postProcessIntent(intent); postProcessIntent(intent);
} else if(cls == Folder.class && do_scale) { } else if (cls == Folder.class && do_scale) {
Folder f = (Folder)i; Folder f = (Folder) i;
FolderConfig fc = f.getFolderConfig(); FolderConfig fc = f.getFolderConfig();
if(fc != pfc) { if (fc != pfc) {
if(fc.wAH == Box.AlignH.CUSTOM || fc.wAV == Box.AlignV.CUSTOM || fc.wW!=0 || fc.wH!=0) { if (fc.wAH == Box.AlignH.CUSTOM || fc.wAV == Box.AlignV.CUSTOM || fc.wW != 0 || fc.wH != 0) {
fc.wX *= sx; fc.wX *= sx;
fc.wY *= sy; fc.wY *= sy;
fc.wW *= sx; fc.wW *= sx;
@ -354,7 +354,7 @@ public class PageProcessor {
} }
private String translateScriptAction(String data) { private String translateScriptAction(String data) {
if(data == null || translated_script_ids == null) { if (data == null || translated_script_ids == null) {
return null; return null;
} }
@ -363,22 +363,22 @@ public class PageProcessor {
int oldScriptId = id_data.first; int oldScriptId = id_data.first;
int newScriptId = translated_script_ids.get(oldScriptId); int newScriptId = translated_script_ids.get(oldScriptId);
return Script.encodeIdAndData(newScriptId, id_data.second); return Script.encodeIdAndData(newScriptId, id_data.second);
} catch(NumberFormatException e) { } catch (NumberFormatException e) {
// pass // pass
return null; return null;
} }
} }
private String postProcessData(int action, String data) { 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 { try {
int old_folder_page_id = Integer.parseInt(data); int old_folder_page_id = Integer.parseInt(data);
int new_folder_page_id = translated_page_ids.get(old_folder_page_id); int new_folder_page_id = translated_page_ids.get(old_folder_page_id);
return String.valueOf(new_folder_page_id); return String.valueOf(new_folder_page_id);
} catch(NumberFormatException e) { } catch (NumberFormatException e) {
// pass // pass
} }
} else if(action == GlobalConfig.RUN_SCRIPT && translated_script_ids != null) { } else if (action == GlobalConfig.RUN_SCRIPT && translated_script_ids != null) {
return translateScriptAction(data); return translateScriptAction(data);
} }
@ -389,25 +389,25 @@ public class PageProcessor {
boolean modified = false; boolean modified = false;
ComponentName cn = intent.getComponent(); ComponentName cn = intent.getComponent();
if(cn != null) { if (cn != null) {
if(cn.equals(drawer_from)) { if (cn.equals(drawer_from)) {
intent.setComponent(drawer_to); intent.setComponent(drawer_to);
modified = true; 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())); intent.setComponent(new ComponentName(pkg_name_to, cn.getClassName()));
modified = true; modified = true;
} }
cn = intent.getComponent(); cn = intent.getComponent();
if(cn.getPackageName().equals(pkg_name_to)) { if (cn.getPackageName().equals(pkg_name_to)) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP) && translated_page_ids != null) { if (intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP) && translated_page_ids != null) {
int old_bookmark_page = intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, Page.NONE); 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)); intent.putExtra(LightningIntent.INTENT_EXTRA_DESKTOP, translated_page_ids.get(old_bookmark_page));
modified = true; modified = true;
} else { } else {
EventAction ea = Utils.decodeEventActionFromLightningIntent(intent); EventAction ea = Utils.decodeEventActionFromLightningIntent(intent);
if(ea != null) { if (ea != null) {
if(postProcessEventAction(ea)) { if (postProcessEventAction(ea)) {
intent.removeExtra(LightningIntent.INTENT_EXTRA_ACTION); intent.removeExtra(LightningIntent.INTENT_EXTRA_ACTION);
intent.removeExtra(LightningIntent.INTENT_EXTRA_DATA); intent.removeExtra(LightningIntent.INTENT_EXTRA_DATA);
intent.putExtra(LightningIntent.INTENT_EXTRA_EVENT_ACTION, JsonLoader.toJSONObject(ea, null).toString()); intent.putExtra(LightningIntent.INTENT_EXTRA_EVENT_ACTION, JsonLoader.toJSONObject(ea, null).toString());
@ -416,10 +416,10 @@ public class PageProcessor {
} }
} }
if(do_scale) { if (do_scale) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) { if (intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
boolean absolute = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, true); 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_X, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_X, 0) * sx);
intent.putExtra(LightningIntent.INTENT_EXTRA_Y, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0) * sy); intent.putExtra(LightningIntent.INTENT_EXTRA_Y, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0) * sy);
modified = true; modified = true;
@ -434,11 +434,11 @@ public class PageProcessor {
private boolean postProcessEventAction(EventAction ea) { private boolean postProcessEventAction(EventAction ea) {
boolean res = false; 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 { try {
Intent intent = Intent.parseUri(ea.data, 0); Intent intent = Intent.parseUri(ea.data, 0);
boolean modified = postProcessIntent(intent); boolean modified = postProcessIntent(intent);
if(modified) { if (modified) {
ea.data = intent.toUri(0); ea.data = intent.toUri(0);
} }
res = modified; res = modified;
@ -447,13 +447,13 @@ public class PageProcessor {
} }
} else { } else {
String new_data = postProcessData(ea.action, ea.data); String new_data = postProcessData(ea.action, ea.data);
if(new_data != null) { if (new_data != null) {
ea.data = new_data; ea.data = new_data;
res = true; res = true;
} }
} }
if(ea.next != null) { if (ea.next != null) {
return postProcessEventAction(ea.next) || res; return postProcessEventAction(ea.next) || res;
} else { } else {
return res; return res;

View file

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

View file

@ -5,7 +5,7 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.*; import android.graphics.Rect;
import net.pierrox.lightning_launcher.LLApp; import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.configuration.JsonFields; import net.pierrox.lightning_launcher.configuration.JsonFields;
@ -17,121 +17,117 @@ import org.json.JSONObject;
public class Widget extends Item { public class Widget extends Item {
public static final int NO_APP_WIDGET_ID = -1; public static final int NO_APP_WIDGET_ID = -1;
// mAppWidgetId is -1 for LL Widget // mAppWidgetId is -1 for LL Widget
private int mAppWidgetId=NO_APP_WIDGET_ID; private int mAppWidgetId = NO_APP_WIDGET_ID;
private ComponentName mComponentName; private ComponentName mComponentName;
private String mAppWidgetLabel; private String mAppWidgetLabel;
public Widget(Page page) { public Widget(Page page) {
super(page); super(page);
} }
protected void copyTo(Item item) { public static Widget createStatic(Page page, int id, Rect cell_p, Rect cell_l, ComponentName cn, int app_widget_id) {
super.copyTo(item); Widget widget = new Widget(page);
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 void setAppWidgetLabel(String label) { widget.init(id, cell_p, cell_l);
mAppWidgetLabel = label;
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() { public String getAppWidgetLabel() {
return mAppWidgetLabel; return mAppWidgetLabel;
} }
public ComponentName getComponentName() { public void setAppWidgetLabel(String label) {
return mComponentName; mAppWidgetLabel = label;
}
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 onConfigure(Context context) { public ComponentName getComponentName() {
AppWidgetManager app_widget_manager=AppWidgetManager.getInstance(LLApp.get()); return mComponentName;
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);
try { public void setComponentName(ComponentName cn) {
context.startActivity(intent); mComponentName = cn;
} catch(Exception e) { }
// pass
}
}
}
@Override public boolean hasConfigurationScreen() {
public void onRemove(boolean keepResources) { AppWidgetManager app_widget_manager = AppWidgetManager.getInstance(LLApp.get());
super.onRemove(keepResources); AppWidgetProviderInfo app_widget_info = app_widget_manager.getAppWidgetInfo(mAppWidgetId);
if(!keepResources) { return app_widget_info != null && app_widget_info.configure != null;
LLApp.get().getAppWidgetHost().deleteAppWidgetId(mAppWidgetId); }
}
}
@Override public void onConfigure(Context context) {
public void createFromJSONObject(JSONObject o) throws JSONException { AppWidgetManager app_widget_manager = AppWidgetManager.getInstance(LLApp.get());
readItemFromJSONObject(o); AppWidgetProviderInfo app_widget_info = app_widget_manager.getAppWidgetInfo(mAppWidgetId);
if (app_widget_info != null && app_widget_info.configure != null) {
mAppWidgetId=o.optInt(JsonFields.WIDGET_APP_WIDGET_ID, NO_APP_WIDGET_ID); Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
String cn=o.optString(JsonFields.WIDGET_COMPONENT_NAME, null); intent.setComponent(app_widget_info.configure);
if(cn!=null) { intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
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);
widget.init(id, cell_p, cell_l); try {
context.startActivity(intent);
widget.mComponentName=cn; } catch (Exception e) {
widget.mAppWidgetId=app_widget_id; // pass
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; @Override
} public void onRemove(boolean keepResources) {
super.onRemove(keepResources);
if (!keepResources) {
LLApp.get().getAppWidgetHost().deleteAppWidgetId(mAppWidgetId);
}
}
@Override @Override
public ItemView createView(Context context) { public void createFromJSONObject(JSONObject o) throws JSONException {
return new WidgetView(context, this); 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; import java.util.List;
public class LightningEngine implements Page.PageListener { public class LightningEngine implements Page.PageListener {
public interface GlobalConfigListener {
void onGlobalConfigChanged(GlobalConfig newGlobalConfig);
}
private static final int GLOBAL_CONFIG_FILE_VERSION = 7; 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; 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 GlobalConfig mGlobalConfig;
private ArrayList<GlobalConfigListener> mGlobalConfigListeners = new ArrayList<>();
private ArrayList<Page.PageListener> mPageListeners = new ArrayList<>();
private Handler mHandler;
private int mResumedPagesCount; private int mResumedPagesCount;
private JSONObject mLaunchStatistics; private JSONObject mLaunchStatistics;
private JSONObject mAppShortcuts; 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) { public LightningEngine(Context context, File baseDir) {
mContext = context; mContext = context;
@ -105,34 +112,33 @@ public class LightningEngine implements Page.PageListener {
} }
/** /**
*
* @return true if upgrade of old free version * @return true if upgrade of old free version
*/ */
public void migrate() { public void migrate() {
if(shouldDoFirstTimeInit()) { if (shouldDoFirstTimeInit()) {
// new install, nothing to migrate // new install, nothing to migrate
return; return;
} }
int from_version=mGlobalConfig.version; int from_version = mGlobalConfig.version;
if(from_version == 1) { 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 // 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 // save the global config now to keep track of the version now
saveGlobalConfig(); saveGlobalConfig();
return; return;
} }
// migrate here (nothing yet) // migrate here (nothing yet)
// update the version number now // update the version number now
if(from_version<GLOBAL_CONFIG_FILE_VERSION) { if (from_version < GLOBAL_CONFIG_FILE_VERSION) {
saveGlobalConfig(); saveGlobalConfig();
} }
} }
public boolean shouldDoFirstTimeInit() { public boolean shouldDoFirstTimeInit() {
int h = mGlobalConfig.homeScreen; int h = mGlobalConfig.homeScreen;
if(h != Page.FIRST_DASHBOARD_PAGE) { if (h != Page.FIRST_DASHBOARD_PAGE) {
return false; return false;
} }
@ -182,25 +188,25 @@ public class LightningEngine implements Page.PageListener {
return page.findItemById(id); return page.findItemById(id);
} }
public Pair<Page,Folder> getPageAndOpenerFromPath(ContainerPath path) { public Pair<Page, Folder> getPageAndOpenerFromPath(ContainerPath path) {
int id = path.getLast(); int id = path.getLast();
if(path.getParent() == null) { if (path.getParent() == null) {
Page page = getOrLoadPage(id); Page page = getOrLoadPage(id);
if(id == Page.USER_MENU_PAGE) { if (id == Page.USER_MENU_PAGE) {
return new Pair<>(page, (Folder)page.findItemById(Utils.USER_MENU_ITEM_ID)); return new Pair<>(page, (Folder) page.findItemById(Utils.USER_MENU_ITEM_ID));
} else { } else {
return new Pair<>(page, null); return new Pair<>(page, null);
} }
} else { } else {
Item item = getItemById(id); Item item = getItemById(id);
if(item instanceof Folder) { if (item instanceof Folder) {
Folder folder = (Folder) item; Folder folder = (Folder) item;
return new Pair<>(folder.getOrLoadFolderPage(), folder); return new Pair<>(folder.getOrLoadFolderPage(), folder);
} else { } else {
// not a folder? maybe a shortcut with a open folder action // not a folder? maybe a shortcut with a open folder action
if(item instanceof Shortcut) { if (item instanceof Shortcut) {
Intent intent = ((Shortcut) item).getIntent(); Intent intent = ((Shortcut) item).getIntent();
if(LLApp.get().isLightningIntent(intent)) { if (LLApp.get().isLightningIntent(intent)) {
EventAction eventAction = Utils.decodeEventActionFromLightningIntent(intent); EventAction eventAction = Utils.decodeEventActionFromLightningIntent(intent);
if (eventAction != null) { if (eventAction != null) {
int folderPage = Integer.parseInt(eventAction.data); int folderPage = Integer.parseInt(eventAction.data);
@ -226,7 +232,6 @@ public class LightningEngine implements Page.PageListener {
return mGlobalConfig.runScripts; return mGlobalConfig.runScripts;
} }
@Override @Override
public void onPageModified(Page page) { public void onPageModified(Page page) {
Utils.updateContainerIconIfNeeded(page); Utils.updateContainerIconIfNeeded(page);
@ -249,7 +254,7 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPageItemAdded(item); for (Page.PageListener listener : mPageListeners) listener.onPageItemAdded(item);
Intent intent = getAppShortcutIntent(item); Intent intent = getAppShortcutIntent(item);
if(intent != null) { if (intent != null) {
String pkg = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG); String pkg = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG);
String id = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID); String id = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID);
pinAppShortcut(pkg, id); pinAppShortcut(pkg, id);
@ -257,7 +262,7 @@ public class LightningEngine implements Page.PageListener {
Page page = item.getPage(); Page page = item.getPage();
Utils.updateContainerIconIfNeeded(page); 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()); IconPack.applyIconPackSync(mContext, page.config.iconPack, page, item.getId());
} }
} }
@ -270,7 +275,7 @@ public class LightningEngine implements Page.PageListener {
@Override @Override
public void onPageItemRemoved(Page page, Item item) { public void onPageItemRemoved(Page page, Item item) {
Intent intent = getAppShortcutIntent(item); Intent intent = getAppShortcutIntent(item);
if(intent != null) { if (intent != null) {
String pkg = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG); String pkg = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG);
String id = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID); String id = intent.getStringExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID);
unpinAppShortcut(pkg, 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 // 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 // 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); Page.PageListener listener = mPageListeners.get(i);
listener.onPageItemRemoved(page, item); listener.onPageItemRemoved(page, item);
} }
@ -291,15 +296,16 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPageItemChanged(page, item); for (Page.PageListener listener : mPageListeners) listener.onPageItemChanged(page, item);
// TODO move this into Screen // TODO move this into Screen
if(item instanceof Folder) { if (item instanceof Folder) {
onPageFolderWindowChanged(page, (Folder)item); onPageFolderWindowChanged(page, (Folder) item);
} }
} }
@Override @Override
public void onPageItemZIndexChanged(Page page, int old_index, int new_index) { public void onPageItemZIndexChanged(Page page, int old_index, int new_index) {
Utils.updateContainerIconIfNeeded(page); 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 @Override
@ -307,7 +313,7 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPagePaused(page); for (Page.PageListener listener : mPageListeners) listener.onPagePaused(page);
mResumedPagesCount--; mResumedPagesCount--;
if(mResumedPagesCount == 0) { if (mResumedPagesCount == 0) {
mBuiltinDataCollectors.pause(); mBuiltinDataCollectors.pause();
} }
} }
@ -316,7 +322,7 @@ public class LightningEngine implements Page.PageListener {
public void onPageResumed(Page page) { public void onPageResumed(Page page) {
for (Page.PageListener listener : mPageListeners) listener.onPageResumed(page); for (Page.PageListener listener : mPageListeners) listener.onPageResumed(page);
if(mResumedPagesCount == 0) { if (mResumedPagesCount == 0) {
mBuiltinDataCollectors.resume(); mBuiltinDataCollectors.resume();
} }
mResumedPagesCount++; mResumedPagesCount++;
@ -324,7 +330,8 @@ public class LightningEngine implements Page.PageListener {
@Override @Override
public void onPageFolderWindowChanged(Page page, Folder folder) { 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 @Override
@ -363,7 +370,8 @@ public class LightningEngine implements Page.PageListener {
@Override @Override
public void onItemTransformChanged(Item item, boolean fast) { 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 @Override
@ -373,7 +381,8 @@ public class LightningEngine implements Page.PageListener {
@Override @Override
public void onItemBindingsChanged(Item item, boolean apply) { 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 @Override
@ -389,13 +398,14 @@ public class LightningEngine implements Page.PageListener {
@Override @Override
public void onFolderPageIdChanged(Folder folder, int oldPageId) { public void onFolderPageIdChanged(Folder folder, int oldPageId) {
Utils.updateFolderIcon(folder); Utils.updateFolderIcon(folder);
for (Page.PageListener listener : mPageListeners) listener.onFolderPageIdChanged(folder, oldPageId); for (Page.PageListener listener : mPageListeners)
listener.onFolderPageIdChanged(folder, oldPageId);
} }
@Override @Override
public void onPageRemoved(Page page) { public void onPageRemoved(Page page) {
// see comment for onPageItemRemoved // 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); Page.PageListener listener = mPageListeners.get(i);
listener.onPageRemoved(page); listener.onPageRemoved(page);
} }
@ -406,23 +416,6 @@ public class LightningEngine implements Page.PageListener {
for (Page.PageListener listener : mPageListeners) listener.onPageLoaded(page); 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() { public void saveData() {
cancelDelayedSaveData(); cancelDelayedSaveData();
mSaveDataRunnable.run(); mSaveDataRunnable.run();
@ -453,19 +446,19 @@ public class LightningEngine implements Page.PageListener {
} }
private void evaluateGlobalConfig() { private void evaluateGlobalConfig() {
if(mGlobalConfig.screensOrder==null) { if (mGlobalConfig.screensOrder == null) {
ArrayList<Integer> desktops = new ArrayList<>(); ArrayList<Integer> desktops = new ArrayList<>();
for(int i = Page.FIRST_DASHBOARD_PAGE; i<= Page.LAST_DASHBOARD_PAGE; i++) { for (int i = Page.FIRST_DASHBOARD_PAGE; i <= Page.LAST_DASHBOARD_PAGE; i++) {
if(Page.getPageDir(mBaseDir, i).exists()) { if (Page.getPageDir(mBaseDir, i).exists()) {
desktops.add(i); desktops.add(i);
} }
} }
int n=desktops.size(); int n = desktops.size();
int[] screens_order = new int[n]; int[] screens_order = new int[n];
String[] screens_name = new String[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); Integer page = desktops.get(i);
screens_order[i] = page; screens_order[i] = page;
screens_name[i] = String.valueOf(page); screens_name[i] = String.valueOf(page);
@ -476,12 +469,12 @@ public class LightningEngine implements Page.PageListener {
} }
// make sure that page directories are reserved // make sure that page directories are reserved
for(int p : mGlobalConfig.screensOrder) { for (int p : mGlobalConfig.screensOrder) {
Page.getPageDir(mBaseDir, p).mkdirs(); Page.getPageDir(mBaseDir, p).mkdirs();
} }
Intent s=LLApp.get().getLockscreenServiceIntent(); Intent s = LLApp.get().getLockscreenServiceIntent();
if(s != null) { if (s != null) {
if (mGlobalConfig.lockScreen != Page.NONE) { if (mGlobalConfig.lockScreen != Page.NONE) {
mContext.startService(s); mContext.startService(s);
} else { } else {
@ -490,7 +483,7 @@ public class LightningEngine implements Page.PageListener {
} }
s = LLApp.get().getWindowServiceIntent(); s = LLApp.get().getWindowServiceIntent();
if(s != null && WindowService.isPermissionAllowed(mContext)) { if (s != null && WindowService.isPermissionAllowed(mContext)) {
if (mGlobalConfig.overlayScreen != Page.NONE) { if (mGlobalConfig.overlayScreen != Page.NONE) {
mContext.startService(s); mContext.startService(s);
} else { } else {
@ -511,7 +504,7 @@ public class LightningEngine implements Page.PageListener {
public void notifyGlobalConfigChanged() { public void notifyGlobalConfigChanged() {
evaluateGlobalConfig(); evaluateGlobalConfig();
for(GlobalConfigListener l : mGlobalConfigListeners) { for (GlobalConfigListener l : mGlobalConfigListeners) {
l.onGlobalConfigChanged(mGlobalConfig); l.onGlobalConfigChanged(mGlobalConfig);
} }
} }
@ -519,12 +512,15 @@ public class LightningEngine implements Page.PageListener {
/************************************** LAUNCH STATISTICS *************************************/ /************************************** LAUNCH STATISTICS *************************************/
public void updateLaunchStatisticsForShortcut(Shortcut shortcut) { public void updateLaunchStatisticsForShortcut(Shortcut shortcut) {
Intent intent=new Intent(shortcut.getIntent()); Intent intent = new Intent(shortcut.getIntent());
ComponentName cn=intent.getComponent(); ComponentName cn = intent.getComponent();
if(cn!=null) { if (cn != null) {
String key=cn.flattenToShortString(); String key = cn.flattenToShortString();
int count = mLaunchStatistics.optInt(key); 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() { private void loadLaunchStatistics() {
File statistics_file = FileUtils.getStatisticsFile(mBaseDir); File statistics_file = FileUtils.getStatisticsFile(mBaseDir);
mLaunchStatistics = FileUtils.readJSONObjectFromFile(statistics_file); mLaunchStatistics = FileUtils.readJSONObjectFromFile(statistics_file);
if(mLaunchStatistics==null) { if (mLaunchStatistics == null) {
mLaunchStatistics = new JSONObject(); mLaunchStatistics = new JSONObject();
} }
} }
@ -552,25 +548,21 @@ public class LightningEngine implements Page.PageListener {
try { try {
File out = FileUtils.getStatisticsFile(mBaseDir); File out = FileUtils.getStatisticsFile(mBaseDir);
FileUtils.saveStringToFile(mLaunchStatistics.toString(), out); FileUtils.saveStringToFile(mLaunchStatistics.toString(), out);
} catch(Exception e) { } catch (Exception e) {
// pass // pass
} }
} }
/************************************** ANDROID 7.1 APP SHORTCUTS *************************************/
private static final String TOKEN_PIN_COUNT = "pinCount";
private void pinAppShortcut(String pkg, String id) { private void pinAppShortcut(String pkg, String id) {
int pinCount = adjustAppShortcutPinCount(pkg, id, 1); int pinCount = adjustAppShortcutPinCount(pkg, id, 1);
if(pinCount == 1) { if (pinCount == 1) {
updatePinnedAppShortcuts(pkg); updatePinnedAppShortcuts(pkg);
} }
} }
private void unpinAppShortcut(String pkg, String id) { private void unpinAppShortcut(String pkg, String id) {
int pinCount = adjustAppShortcutPinCount(pkg, id, -1); int pinCount = adjustAppShortcutPinCount(pkg, id, -1);
if(pinCount == 0) { if (pinCount == 0) {
updatePinnedAppShortcuts(pkg); updatePinnedAppShortcuts(pkg);
} }
} }
@ -579,7 +571,7 @@ public class LightningEngine implements Page.PageListener {
private void updatePinnedAppShortcuts(String pkg) { private void updatePinnedAppShortcuts(String pkg) {
LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE); LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
List<String> pinnedAppShortcutIds = getPinnedAppShortcutIds(pkg); List<String> pinnedAppShortcutIds = getPinnedAppShortcutIds(pkg);
if(launcherApps.hasShortcutHostPermission()) { if (launcherApps.hasShortcutHostPermission()) {
launcherApps.pinShortcuts(pkg, pinnedAppShortcutIds, Process.myUserHandle()); launcherApps.pinShortcuts(pkg, pinnedAppShortcutIds, Process.myUserHandle());
} }
} }
@ -587,13 +579,13 @@ public class LightningEngine implements Page.PageListener {
private List<String> getPinnedAppShortcutIds(String pkg) { private List<String> getPinnedAppShortcutIds(String pkg) {
ArrayList<String> ids = new ArrayList<>(); ArrayList<String> ids = new ArrayList<>();
JSONObject appShortcutsForPackage = mAppShortcuts.optJSONObject(pkg); JSONObject appShortcutsForPackage = mAppShortcuts.optJSONObject(pkg);
if(appShortcutsForPackage != null) { if (appShortcutsForPackage != null) {
Iterator<String> keys = appShortcutsForPackage.keys(); Iterator<String> keys = appShortcutsForPackage.keys();
while(keys.hasNext()) { while (keys.hasNext()) {
String id = keys.next(); String id = keys.next();
JSONObject appShortcut = appShortcutsForPackage.optJSONObject(id); JSONObject appShortcut = appShortcutsForPackage.optJSONObject(id);
int pinCount = appShortcut.optInt(TOKEN_PIN_COUNT, 0); int pinCount = appShortcut.optInt(TOKEN_PIN_COUNT, 0);
if(pinCount > 0) { if (pinCount > 0) {
ids.add(id); ids.add(id);
} }
} }
@ -604,7 +596,7 @@ public class LightningEngine implements Page.PageListener {
private int adjustAppShortcutPinCount(String pkg, String id, int increment) { private int adjustAppShortcutPinCount(String pkg, String id, int increment) {
try { try {
JSONObject appShortcutsForPackage = mAppShortcuts.optJSONObject(pkg); JSONObject appShortcutsForPackage = mAppShortcuts.optJSONObject(pkg);
if(appShortcutsForPackage == null) { if (appShortcutsForPackage == null) {
appShortcutsForPackage = new JSONObject(); appShortcutsForPackage = new JSONObject();
mAppShortcuts.put(pkg, appShortcutsForPackage); 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) { private Intent getAppShortcutIntent(Item item) {
if (item.getClass() == Shortcut.class) { if (item.getClass() == Shortcut.class) {
Shortcut shortcut = (Shortcut) item; Shortcut shortcut = (Shortcut) item;
@ -662,13 +656,13 @@ public class LightningEngine implements Page.PageListener {
} }
public int readCurrentPage(int default_page) { public int readCurrentPage(int default_page) {
String p=FileUtils.readFileContent(getCurrentPagerPageFile()); String p = FileUtils.readFileContent(getCurrentPagerPageFile());
int page; int page;
try { try {
page=Integer.parseInt(p); page = Integer.parseInt(p);
} catch(Exception e) { } catch (Exception e) {
// catch NPE (if p==null) and NumberFormatException // catch NPE (if p==null) and NumberFormatException
page=default_page; page = default_page;
} }
return page; return page;
} }
@ -685,15 +679,15 @@ public class LightningEngine implements Page.PageListener {
public ArrayList<Folder> findAllFolderPageOpeners(int folder_page) { public ArrayList<Folder> findAllFolderPageOpeners(int folder_page) {
ArrayList<Folder> openers = new ArrayList<>(); ArrayList<Folder> openers = new ArrayList<>();
for(int n : mPageManager.getAllPagesIds()) { for (int n : mPageManager.getAllPagesIds()) {
if(n == folder_page && folder_page != Page.USER_MENU_PAGE) continue; if (n == folder_page && folder_page != Page.USER_MENU_PAGE) continue;
Page p = mPageManager.getOrLoadPage(n); Page p = mPageManager.getOrLoadPage(n);
for(Item item : p.items) { for (Item item : p.items) {
if(item instanceof Folder) { if (item instanceof Folder) {
Folder f=(Folder)item; Folder f = (Folder) item;
if(f.getFolderPageId()==folder_page) { if (f.getFolderPageId() == folder_page) {
openers.add(f); openers.add(f);
} }
} }
@ -704,22 +698,22 @@ public class LightningEngine implements Page.PageListener {
} }
public Folder findFirstFolderPageOpener(int folder_page) { public Folder findFirstFolderPageOpener(int folder_page) {
if(!Page.isFolder(folder_page)) { if (!Page.isFolder(folder_page)) {
return null; return null;
} }
ArrayList<Page> pages=mPageManager.getLoadedPages(); ArrayList<Page> pages = mPageManager.getLoadedPages();
for(Page p : pages) { for (Page p : pages) {
// skip the page containing this item to avoid nasty recursive calls, except for the user menu which includes its opener // 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); mPageManager.getOrLoadPage(p.id);
} }
for(Item item : p.items) { for (Item item : p.items) {
if(item instanceof Folder) { if (item instanceof Folder) {
Folder f=(Folder)item; Folder f = (Folder) item;
if(f.getFolderPageId()==folder_page) { if (f.getFolderPageId() == folder_page) {
return f; return f;
} }
} }
@ -727,22 +721,22 @@ public class LightningEngine implements Page.PageListener {
} }
// not found in currently loaded pages, try again with unloaded pages // 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); Page p = mPageManager.getPage(n);
if(p != null) { if (p != null) {
// already traversed in the loop above // already traversed in the loop above
continue; continue;
} }
p = mPageManager.getOrLoadPage(n); p = mPageManager.getOrLoadPage(n);
if(p.id == folder_page) continue; if (p.id == folder_page) continue;
for(Item item : p.items) { for (Item item : p.items) {
if(item instanceof Folder) { if (item instanceof Folder) {
Folder f=(Folder)item; Folder f = (Folder) item;
if(f.getFolderPageId()==folder_page) { if (f.getFolderPageId() == folder_page) {
return f; return f;
} }
} }
@ -753,15 +747,19 @@ public class LightningEngine implements Page.PageListener {
} }
public void setFloatingDesktopVisibility(boolean visible) { public void setFloatingDesktopVisibility(boolean visible) {
if(mGlobalConfig.overlayScreen != Page.NONE) { if (mGlobalConfig.overlayScreen != Page.NONE) {
Intent f = LLApp.get().getWindowServiceIntent(); Intent f = LLApp.get().getWindowServiceIntent();
f.setAction(visible ? WindowService.INTENT_ACTION_SHOW : WindowService.INTENT_ACTION_HIDE); f.setAction(visible ? WindowService.INTENT_ACTION_SHOW : WindowService.INTENT_ACTION_HIDE);
mContext.startService(f); mContext.startService(f);
} }
} }
public interface GlobalConfigListener {
void onGlobalConfigChanged(GlobalConfig newGlobalConfig);
}
public class PageManager { public class PageManager {
private ArrayList<Page> mPages = new ArrayList<>(); private final ArrayList<Page> mPages = new ArrayList<>();
private PageManager() { private PageManager() {
} }
@ -772,13 +770,13 @@ public class LightningEngine implements Page.PageListener {
public int[] getAllPagesIds() { public int[] getAllPagesIds() {
String[] allPageNames = FileUtils.getPagesDir(mBaseDir).list(); String[] allPageNames = FileUtils.getPagesDir(mBaseDir).list();
if(allPageNames == null) { if (allPageNames == null) {
return new int[0]; return new int[0];
} }
int length = allPageNames.length; int length = allPageNames.length;
int[] allPagesIds = new int[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]); allPagesIds[n] = Integer.parseInt(allPageNames[n]);
} }
return allPagesIds; return allPagesIds;
@ -793,8 +791,8 @@ public class LightningEngine implements Page.PageListener {
} }
public Page getPage(int id) { public Page getPage(int id) {
for(Page page : mPages) { for (Page page : mPages) {
if(page.id == id) { if (page.id == id) {
return page; return page;
} }
} }
@ -804,7 +802,7 @@ public class LightningEngine implements Page.PageListener {
public Page getOrLoadPage(int id) { public Page getOrLoadPage(int id) {
Page page = getPage(id); Page page = getPage(id);
if(page != null) { if (page != null) {
return page; return page;
} }
@ -817,7 +815,7 @@ public class LightningEngine implements Page.PageListener {
} }
public void savePagesSync() { public void savePagesSync() {
for(Page p : new ArrayList<Page>(mPages)) { for (Page p : new ArrayList<Page>(mPages)) {
p.save(); p.save();
} }
} }
@ -848,7 +846,7 @@ public class LightningEngine implements Page.PageListener {
// reserve copied page ids // reserve copied page ids
SparseIntArray translated_page_ids = new SparseIntArray(); 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()); int new_page_id = Page.reservePage(mBaseDir, to_translate.isFolder());
translated_page_ids.put(to_translate.id, new_page_id); translated_page_ids.put(to_translate.id, new_page_id);
} }
@ -856,7 +854,7 @@ public class LightningEngine implements Page.PageListener {
// copy and translate pages // copy and translate pages
PageProcessor page_processor = new PageProcessor(); PageProcessor page_processor = new PageProcessor();
page_processor.setTranslatedPageIds(translated_page_ids); 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); 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_VOLTAGE = "bat_voltage";
private static final String VAR_PLUGGED = "bat_plugged"; private static final String VAR_PLUGGED = "bat_plugged";
private Context mContext; private final Context mContext;
private BroadcastReceiver mBatteryReceiver; private final BroadcastReceiver mBatteryReceiver;
/*package*/ BatteryDataCollector(Context context, final VariableManager vm) { /*package*/ BatteryDataCollector(Context context, final VariableManager vm) {
mContext = context; mContext = context;
mBatteryReceiver=new BroadcastReceiver() { mBatteryReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
int level=intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale=intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
int status=intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN); int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
int voltage=intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
int plugged=intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
vm.setVariable(VAR_LEVEL, level*100/scale); vm.setVariable(VAR_LEVEL, level * 100 / scale);
vm.setVariable(VAR_STATUS, status); vm.setVariable(VAR_STATUS, status);
vm.setVariable(VAR_VOLTAGE, voltage); vm.setVariable(VAR_VOLTAGE, voltage);
vm.setVariable(VAR_PLUGGED, plugged); vm.setVariable(VAR_PLUGGED, plugged);
@ -53,7 +53,7 @@ import net.pierrox.lightning_launcher.R;
@Override @Override
public BuiltinVariable[] getBuiltinVariables(Resources resources) { public BuiltinVariable[] getBuiltinVariables(Resources resources) {
return new BuiltinVariable[] { return new BuiltinVariable[]{
new BuiltinVariable(VAR_LEVEL, resources.getString(R.string.bv_batl)), new BuiltinVariable(VAR_LEVEL, resources.getString(R.string.bv_batl)),
new BuiltinVariable(VAR_STATUS, resources.getString(R.string.bv_batst)), new BuiltinVariable(VAR_STATUS, resources.getString(R.string.bv_batst)),
new BuiltinVariable(VAR_VOLTAGE, resources.getString(R.string.bv_batv)), 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) { public boolean equals(Binding other) {
if(target == null && other.target!=null || (target != null && !target.equals(other.target))) return false; if (target == null && other.target != null || (target != null && !target.equals(other.target)))
if(formula == null && other.formula!=null || (formula != null && !formula.equals(other.formula))) return false; return false;
return true; 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_WIDTH = "screen_width";
private static final String VAR_SCREEN_HEIGHT = "screen_height"; private static final String VAR_SCREEN_HEIGHT = "screen_height";
private Pair<String,BuiltinVariable[]>[] mBuiltinVariables; private final Pair<String, BuiltinVariable[]>[] mBuiltinVariables;
private Handler mHandler; private final Handler mHandler;
private VariableManager mVariableManager; private final VariableManager mVariableManager;
private DataCollector[] mDataCollectors; private final DataCollector[] mDataCollectors;
private int mResumedCount; private int mResumedCount;
public BuiltinDataCollectors(Context context, VariableManager vm) { public BuiltinDataCollectors(Context context, VariableManager vm) {
@ -26,7 +26,7 @@ public class BuiltinDataCollectors {
StorageDataCollector storageDataCollector = new StorageDataCollector(context, mHandler, mVariableManager); StorageDataCollector storageDataCollector = new StorageDataCollector(context, mHandler, mVariableManager);
BatteryDataCollector batteryDataCollector = new BatteryDataCollector(context, mVariableManager); BatteryDataCollector batteryDataCollector = new BatteryDataCollector(context, mVariableManager);
CpuDataCollector cpuDataCollector = new CpuDataCollector(mHandler, mVariableManager); CpuDataCollector cpuDataCollector = new CpuDataCollector(mHandler, mVariableManager);
mDataCollectors = new DataCollector[] { mDataCollectors = new DataCollector[]{
timeDataCollector, timeDataCollector,
storageDataCollector, storageDataCollector,
batteryDataCollector, batteryDataCollector,
@ -35,13 +35,13 @@ public class BuiltinDataCollectors {
Resources resources = context.getResources(); Resources resources = context.getResources();
BuiltinVariable[] screen_variables = new BuiltinVariable[] { BuiltinVariable[] screen_variables = new BuiltinVariable[]{
new BuiltinVariable(VAR_SCREEN_ORIENTATION, resources.getString(R.string.bv_o)), 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_WIDTH, resources.getString(R.string.gb_w)),
new BuiltinVariable(VAR_SCREEN_HEIGHT, resources.getString(R.string.gb_h)), 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_dt), timeDataCollector.getBuiltinVariables(resources)),
new Pair<>(resources.getString(R.string.bvc_screen), screen_variables), new Pair<>(resources.getString(R.string.bvc_screen), screen_variables),
new Pair<>(resources.getString(R.string.bvc_stor), storageDataCollector.getBuiltinVariables(resources)), new Pair<>(resources.getString(R.string.bvc_stor), storageDataCollector.getBuiltinVariables(resources)),
@ -51,11 +51,11 @@ public class BuiltinDataCollectors {
} }
public void end() { public void end() {
for(DataCollector collector : mDataCollectors) collector.end(); for (DataCollector collector : mDataCollectors) collector.end();
} }
public void resume() { public void resume() {
if(mResumedCount == 0) { if (mResumedCount == 0) {
for (DataCollector collector : mDataCollectors) collector.onResume(); for (DataCollector collector : mDataCollectors) collector.onResume();
} }
mResumedCount++; mResumedCount++;
@ -63,12 +63,12 @@ public class BuiltinDataCollectors {
public void pause() { public void pause() {
mResumedCount--; mResumedCount--;
if(mResumedCount == 0) { if (mResumedCount == 0) {
for(DataCollector collector : mDataCollectors) collector.onPause(); for (DataCollector collector : mDataCollectors) collector.onPause();
} }
} }
public Pair<String,BuiltinVariable[]>[] getBuiltinVariables() { public Pair<String, BuiltinVariable[]>[] getBuiltinVariables() {
return mBuiltinVariables; return mBuiltinVariables;
} }

View file

@ -10,70 +10,22 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
public class CpuDataCollector extends PollingDataCollector { public class CpuDataCollector extends PollingDataCollector {
// private static String VAR_COUNT = "cpu_count"; // private static String VAR_COUNT = "cpu_count";
private static String VAR_USAGE = "cpu_usage"; private static final String VAR_USAGE = "cpu_usage";
private static String VAR_USER = "cpu_user"; private static final String VAR_USER = "cpu_user";
private static String VAR_NICE = "cpu_nice"; private static final String VAR_NICE = "cpu_nice";
private static String VAR_SYSTEM = "cpu_system"; private static final String VAR_SYSTEM = "cpu_system";
private static String VAR_IDLE = "cpu_idle"; private static final String VAR_IDLE = "cpu_idle";
private static String VAR_IOWAIT = "cpu_iowait"; private static final String VAR_IOWAIT = "cpu_iowait";
private static String VAR_IRQ = "cpu_irq"; private static final String VAR_IRQ = "cpu_irq";
private static String VAR_SOFTIRQ = "cpu_softirq"; private static final 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 CpuUsage mPreviousUsage; private CpuUsage mPreviousUsage;
private CpuUsage mCurrentUsage; private CpuUsage mCurrentUsage;
private final Runnable mSetVariablesRunnable = new Runnable() {
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() {
@Override @Override
public void run() { public void run() {
long delta = mCurrentUsage.total - mPreviousUsage.total; long delta = mCurrentUsage.total - mPreviousUsage.total;
if(delta != 0) { if (delta != 0) {
long user = (mCurrentUsage.total - mCurrentUsage.idle) - (mPreviousUsage.total - mPreviousUsage.idle); long user = (mCurrentUsage.total - mCurrentUsage.idle) - (mPreviousUsage.total - mPreviousUsage.idle);
mVariableManager.edit(); mVariableManager.edit();
mVariableManager.setVariable(VAR_USAGE, percent(user, delta)); 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) { 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) { private void readProcStat(CpuUsage out) {
@ -115,7 +102,20 @@ public class CpuDataCollector extends PollingDataCollector {
} catch (IOException e) { } catch (IOException e) {
// pass // pass
} finally { } 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; import android.content.res.Resources;
public interface DataCollector { public interface DataCollector {
public void onPause(); void onPause();
public void onResume();
public void end(); void onResume();
public BuiltinVariable[] getBuiltinVariables(Resources resources);
void end();
BuiltinVariable[] getBuiltinVariables(Resources resources);
} }

View file

@ -3,7 +3,7 @@ package net.pierrox.lightning_launcher.engine.variable;
import android.os.Handler; import android.os.Handler;
/*package*/ abstract class PollingDataCollector extends Thread implements DataCollector { /*package*/ abstract class PollingDataCollector extends Thread implements DataCollector {
private int mPeriod; private final int mPeriod;
protected Handler mHandler; protected Handler mHandler;
protected VariableManager mVariableManager; protected VariableManager mVariableManager;
private boolean mPaused; private boolean mPaused;
@ -22,7 +22,7 @@ import android.os.Handler;
do { do {
collectData(); collectData();
if(mEnd) break; if (mEnd) break;
try { try {
sleep(mPeriod); sleep(mPeriod);
@ -30,7 +30,7 @@ import android.os.Handler;
// interrupted, will likely end // interrupted, will likely end
} }
if(mPaused) { if (mPaused) {
synchronized (this) { synchronized (this) {
try { try {
wait(); wait();
@ -39,7 +39,7 @@ import android.os.Handler;
} }
} }
} }
} while(!mEnd); } while (!mEnd);
} }
@Override @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_TOTAL_H = "int_total_h";
private static final String VAR_INT_FREE_H = "int_free_h"; private static final String VAR_INT_FREE_H = "int_free_h";
private Context mContext; private final Context mContext;
private final Runnable mSetVariablesRunnable = new Runnable() {
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() {
@Override @Override
public void run() { public void run() {
long int_free; long int_free;
@ -68,9 +42,9 @@ import java.io.File;
block_size = stat.getBlockSize(); block_size = stat.getBlockSize();
total_blocks = stat.getBlockCount(); total_blocks = stat.getBlockCount();
available_blocks = stat.getAvailableBlocks(); available_blocks = stat.getAvailableBlocks();
int_free = available_blocks*block_size; int_free = available_blocks * block_size;
int_total = total_blocks*block_size; int_total = total_blocks * block_size;
} catch(IllegalArgumentException e) { } catch (IllegalArgumentException e) {
int_free = 0; int_free = 0;
int_total = 0; int_total = 0;
} }
@ -83,7 +57,7 @@ import java.io.File;
available_blocks = stat.getAvailableBlocks(); available_blocks = stat.getAvailableBlocks();
ext_free = available_blocks * block_size; ext_free = available_blocks * block_size;
ext_total = total_blocks * block_size; ext_total = total_blocks * block_size;
} catch(IllegalArgumentException e) { } catch (IllegalArgumentException e) {
ext_free = 0; ext_free = 0;
ext_total = 0; ext_total = 0;
} }
@ -100,4 +74,29 @@ import java.io.File;
mVariableManager.commit(); 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_DAY_NAME = "ll_day_name";
private static final String VAR_MONTH_NAME = "ll_month_name"; private static final String VAR_MONTH_NAME = "ll_month_name";
private SimpleDateFormat mDfSecond = new SimpleDateFormat("ss"); private final SimpleDateFormat mDfSecond = new SimpleDateFormat("ss");
private SimpleDateFormat mDfMinute = new SimpleDateFormat("mm"); private final SimpleDateFormat mDfMinute = new SimpleDateFormat("mm");
private SimpleDateFormat mDfHour12 = new SimpleDateFormat("hh"); private final SimpleDateFormat mDfHour12 = new SimpleDateFormat("hh");
private SimpleDateFormat mDfHour24 = new SimpleDateFormat("HH"); private final SimpleDateFormat mDfHour24 = new SimpleDateFormat("HH");
private SimpleDateFormat mDfDay = new SimpleDateFormat("dd"); private final SimpleDateFormat mDfDay = new SimpleDateFormat("dd");
private SimpleDateFormat mDfMonth = new SimpleDateFormat("MM"); private final SimpleDateFormat mDfMonth = new SimpleDateFormat("MM");
private SimpleDateFormat mDfWeek = new SimpleDateFormat("w"); private final SimpleDateFormat mDfWeek = new SimpleDateFormat("w");
private SimpleDateFormat mDfYear = new SimpleDateFormat("yyyy"); private final SimpleDateFormat mDfYear = new SimpleDateFormat("yyyy");
private SimpleDateFormat mDfAmPm = new SimpleDateFormat("a"); private final SimpleDateFormat mDfAmPm = new SimpleDateFormat("a");
private SimpleDateFormat mDfDayName = new SimpleDateFormat("EEEE"); private final SimpleDateFormat mDfDayName = new SimpleDateFormat("EEEE");
private SimpleDateFormat mDfMonthName = new SimpleDateFormat("MMMM"); private final SimpleDateFormat mDfMonthName = new SimpleDateFormat("MMMM");
private int mPreviousSecond = -1; private int mPreviousSecond = -1;
private final Runnable mSetVariablesRunnable = new Runnable() {
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() {
@Override @Override
public void run() { public void run() {
// text fields, but some of them can be converted to integer // text fields, but some of them can be converted to integer
@ -72,8 +43,8 @@ public class TimeDataCollector extends PollingDataCollector {
int second = now.getSeconds(); int second = now.getSeconds();
mVariableManager.edit(); mVariableManager.edit();
mVariableManager.setVariable(VAR_SECOND, mDfSecond.format(now)); mVariableManager.setVariable(VAR_SECOND, mDfSecond.format(now));
mVariableManager.setVariable(VAR_TIMESTAMP, now.getTime()/1000); mVariableManager.setVariable(VAR_TIMESTAMP, now.getTime() / 1000);
if(mPreviousSecond == -1 || second<mPreviousSecond) { if (mPreviousSecond == -1 || second < mPreviousSecond) {
mVariableManager.setVariable(VAR_MINUTE, mDfMinute.format(now)); mVariableManager.setVariable(VAR_MINUTE, mDfMinute.format(now));
mVariableManager.setVariable(VAR_HOUR12, mDfHour12.format(now)); mVariableManager.setVariable(VAR_HOUR12, mDfHour12.format(now));
mVariableManager.setVariable(VAR_HOUR24, mDfHour24.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 @Override
public void onResume() { public void onResume() {
// force an immediate update // 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.data.FileUtils;
import net.pierrox.lightning_launcher.engine.LightningEngine; import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.engine.Screen; 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.Script;
import net.pierrox.lightning_launcher.script.ScriptExecutor; 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.Lightning;
import net.pierrox.lightning_launcher.script.api.Property; import net.pierrox.lightning_launcher.script.api.Property;
import net.pierrox.lightning_launcher.script.api.PropertyEditor; import net.pierrox.lightning_launcher.script.api.PropertyEditor;
@ -40,83 +40,32 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
public class VariableManager { 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_VARIABLES = "v";
private static final String TOK_NAME = "n"; private static final String TOK_NAME = "n";
private static final String TOK_VALUE = "v"; 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) { public VariableManager(LightningEngine engine, File load_values_from) {
mEngine = engine; mEngine = engine;
@ -127,11 +76,11 @@ public class VariableManager {
mValuesFile = load_values_from; mValuesFile = load_values_from;
JSONObject values = FileUtils.readJSONObjectFromFile(load_values_from); JSONObject values = FileUtils.readJSONObjectFromFile(load_values_from);
if(values != null) { if (values != null) {
try { try {
JSONArray jvariables = values.getJSONArray(TOK_VARIABLES); JSONArray jvariables = values.getJSONArray(TOK_VARIABLES);
int l = jvariables.length(); int l = jvariables.length();
for(int i=0; i<l; i++) { for (int i = 0; i < l; i++) {
JSONObject jvariable = jvariables.getJSONObject(i); JSONObject jvariable = jvariables.getJSONObject(i);
String name = jvariable.getString(TOK_NAME); String name = jvariable.getString(TOK_NAME);
Object value = jvariable.get(TOK_VALUE); 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() { public void saveValues() {
try { try {
JSONArray jvariables = new JSONArray(); JSONArray jvariables = new JSONArray();
for(Variable variable : getUserVariables()) { for (Variable variable : getUserVariables()) {
if(variable.value != null) { if (variable.value != null) {
JSONObject jvariable = new JSONObject(); JSONObject jvariable = new JSONObject();
jvariable.put(TOK_NAME, variable.name); jvariable.put(TOK_NAME, variable.name);
jvariable.put(TOK_VALUE, variable.value); jvariable.put(TOK_VALUE, variable.value);
@ -157,7 +119,7 @@ public class VariableManager {
JSONObject jdata = new JSONObject(); JSONObject jdata = new JSONObject();
jdata.put(TOK_VARIABLES, jvariables); jdata.put(TOK_VARIABLES, jvariables);
FileUtils.saveStringToFile(jdata.toString(), mValuesFile); FileUtils.saveStringToFile(jdata.toString(), mValuesFile);
} catch(Exception e) { } catch (Exception e) {
mValuesFile.delete(); mValuesFile.delete();
} }
} }
@ -168,14 +130,14 @@ public class VariableManager {
public void resumeUpdates() { public void resumeUpdates() {
mUpdatesPaused = false; mUpdatesPaused = false;
if(mModifiedVariables != null && mModifiedVariables.size()>0) { if (mModifiedVariables != null && mModifiedVariables.size() > 0) {
commit(); commit();
} }
} }
public Variable getVariable(String name) { public Variable getVariable(String name) {
Variable var = mVariables.get(name); Variable var = mVariables.get(name);
if(var == null) { if (var == null) {
var = new Variable(name, null); var = new Variable(name, null);
mVariables.put(name, var); mVariables.put(name, var);
} }
@ -188,22 +150,22 @@ public class VariableManager {
public ArrayList<Variable> getUserVariables() { public ArrayList<Variable> getUserVariables() {
LLApp llApp = LLApp.get(); 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(); Collection<Variable> all_variables = getAllVariables();
ArrayList<Variable> user_variables = new ArrayList<>(); ArrayList<Variable> user_variables = new ArrayList<>();
for(Variable variable : all_variables) { for (Variable variable : all_variables) {
boolean found = false; boolean found = false;
String name = variable.name; String name = variable.name;
loop: loop:
for(Pair<String,BuiltinVariable[]> p : builtin_variables) { for (Pair<String, BuiltinVariable[]> p : builtin_variables) {
for(BuiltinVariable bv : p.second) { for (BuiltinVariable bv : p.second) {
if(bv.name.equals(name)) { if (bv.name.equals(name)) {
found = true; found = true;
break loop; break loop;
} }
} }
} }
if(!found) { if (!found) {
user_variables.add(variable); user_variables.add(variable);
} }
} }
@ -218,7 +180,7 @@ public class VariableManager {
} }
public void edit() { public void edit() {
if(mModifiedVariables == null) { if (mModifiedVariables == null) {
mModifiedVariables = new HashSet<>(); mModifiedVariables = new HashSet<>();
} }
mDate++; mDate++;
@ -227,10 +189,10 @@ public class VariableManager {
public void setVariable(String name, Object new_value) { public void setVariable(String name, Object new_value) {
Variable variable = getVariable(name); Variable variable = getVariable(name);
Object old_value = variable.value; Object old_value = variable.value;
if((new_value==null && old_value != null) || (new_value != null && !new_value.equals(old_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--) { for (int i = mAnimators.size() - 1; i >= 0; i--) {
Animator animator = mAnimators.get(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); animator.start(animator.done ? Value.asDouble(old_value) : animator.lastValue, Value.asDouble(new_value), mDate);
} }
} }
@ -248,7 +210,7 @@ public class VariableManager {
boolean animate; boolean animate;
String animator_name = Animator.name(var_name, duration, interpolator, offset); String animator_name = Animator.name(var_name, duration, interpolator, offset);
Animator animator = findAnimator(animator_name); 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 // prepare an animator but do not run it, it will be activated upon next variable change
double to = Value.asDouble(new_value); double to = Value.asDouble(new_value);
@ -259,12 +221,12 @@ public class VariableManager {
result = to; result = to;
animate = false; animate = false;
} else { } else {
if(animator.lastValueDate == mDate || animator.done) { if (animator.lastValueDate == mDate || animator.done) {
result = animator.lastValue; result = animator.lastValue;
animate = true; animate = true;
} else { } else {
long delta = AnimationUtils.currentAnimationTimeMillis() - animator.start; long delta = AnimationUtils.currentAnimationTimeMillis() - animator.start;
if(delta <= animator.offset) { if (delta <= animator.offset) {
result = animator.fromValue; result = animator.fromValue;
animate = true; animate = true;
} else { } else {
@ -283,7 +245,7 @@ public class VariableManager {
} }
} }
} }
if(animate && !mAnimateScheduled) { if (animate && !mAnimateScheduled) {
mAnimateScheduled = true; mAnimateScheduled = true;
mHandler.post(mAnimate); mHandler.post(mAnimate);
} }
@ -291,32 +253,22 @@ public class VariableManager {
return result; return result;
} }
private Animator findAnimator(String name) { private final Runnable mAnimate = new Runnable() {
for(Animator a : mAnimators) {
if(name.equals(a.name)) {
return a;
}
}
return null;
}
private Runnable mAnimate = new Runnable() {
@Override @Override
public void run() { public void run() {
edit(); edit();
for(Animator a : mAnimators) { for (Animator a : mAnimators) {
mModifiedVariables.add(getVariable(a.varName)); mModifiedVariables.add(getVariable(a.varName));
} }
commit(); commit();
int done_count = 0; 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); Animator a = mAnimators.get(i);
if(a.done) { if (a.done) {
done_count++; done_count++;
} }
} }
if(mAnimators.size() > done_count) { if (mAnimators.size() > done_count) {
mHandler.post(mAnimate); mHandler.post(mAnimate);
} else { } else {
mAnimateScheduled = false; 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() { public void commit() {
if(!mUpdatesPaused) { if (!mUpdatesPaused) {
if(mTmpModifiedTargets == null) { if (mTmpModifiedTargets == null) {
mTmpModifiedTargets = new ArrayList<>(); mTmpModifiedTargets = new ArrayList<>();
} else { } else {
mTmpModifiedTargets.clear(); mTmpModifiedTargets.clear();
@ -339,7 +300,7 @@ public class VariableManager {
// modifies the item and forces the view to be rebuilt, and as a consequence bindings // 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 // 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. // 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); Target target = targets.get(i);
if (target.dateComputed != mDate) { if (target.dateComputed != mDate) {
Object old_value = target.value; Object old_value = target.value;
@ -362,20 +323,28 @@ public class VariableManager {
// TODO sort targets per page/item in order to group properties changes // TODO sort targets per page/item in order to group properties changes
ScriptExecutor se = mEngine.getScriptExecutor(); ScriptExecutor se = mEngine.getScriptExecutor();
Lightning ll = se.getLightning(); Lightning ll = se.getLightning();
for(Target target : targets) { for (Target target : targets) {
PropertySet ps = ll.getCachedItem(target.itemView).getProperties(); PropertySet ps = ll.getCachedItem(target.itemView).getProperties();
Object value = target.value; Object value = target.value;
if(value != null) { if (value != null) {
String field = target.field; String field = target.field;
PropertyEditor editor = ps.edit(); PropertyEditor editor = ps.edit();
try { try {
switch(Property.getType(field)) { switch (Property.getType(field)) {
case Property.TYPE_BOOLEAN: editor.setBoolean(field, Value.asBoolean(value)); break; case Property.TYPE_BOOLEAN:
case Property.TYPE_INTEGER: editor.setInteger(field, Value.asInteger(value)); break; editor.setBoolean(field, Value.asBoolean(value));
case Property.TYPE_FLOAT: editor.setFloat(field, Value.asFloat(value)); break; break;
case Property.TYPE_STRING: editor.setString(field, Value.asString(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); se.displayScriptError(e);
return; 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(); int formula_length = formula.length();
// decode variable names // decode variable names
HashSet<String> names = new HashSet<>(); HashSet<String> names = new HashSet<>();
int p = -1; int p = -1;
while((p = formula.indexOf('$', p+1)) != -1) { while ((p = formula.indexOf('$', p + 1)) != -1) {
p++; p++;
if(p < formula_length && isIdentifierChar(formula.charAt(p))) { if (p < formula_length && isIdentifierChar(formula.charAt(p))) {
String identifier = getIdentifier(formula, p); String identifier = getIdentifier(formula, p);
if(identifier != null) { if (identifier != null) {
names.add(identifier); names.add(identifier);
} }
} }
@ -404,14 +373,14 @@ public class VariableManager {
names.toArray(variable_names); names.toArray(variable_names);
mTmpStringBuilder.setLength(0); mTmpStringBuilder.setLength(0);
if(!formula.contains("return")) { if (!formula.contains("return")) {
mTmpStringBuilder.append("return "); mTmpStringBuilder.append("return ");
} }
for(p=0; p<formula_length; p++) { for (p = 0; p < formula_length; p++) {
char c = formula.charAt(p); char c = formula.charAt(p);
if(c == '$') { if (c == '$') {
p++; p++;
if(p == formula_length) { if (p == formula_length) {
break; break;
} }
c = formula.charAt(p); c = formula.charAt(p);
@ -424,7 +393,7 @@ public class VariableManager {
public void updateBindings(ItemView itemView, Binding[] bindings, boolean apply, Screen fromScreen, boolean removeOldTargets) { public void updateBindings(ItemView itemView, Binding[] bindings, boolean apply, Screen fromScreen, boolean removeOldTargets) {
// remove old targets // remove old targets
if(removeOldTargets) { if (removeOldTargets) {
ScriptManager sm = mEngine.getScriptManager(); ScriptManager sm = mEngine.getScriptManager();
for (ArrayList<Target> targets : mVariableTargets.values()) { for (ArrayList<Target> targets : mVariableTargets.values()) {
for (int l = targets.size() - 1; l >= 0; l--) { for (int l = targets.size() - 1; l >= 0; l--) {
@ -439,26 +408,26 @@ public class VariableManager {
} }
} }
if(bindings == null) { if (bindings == null) {
return; return;
} }
// add new one // add new one
ScriptManager sm = mEngine.getScriptManager(); ScriptManager sm = mEngine.getScriptManager();
ArrayList<Target> targets = new ArrayList<>(bindings.length); ArrayList<Target> targets = new ArrayList<>(bindings.length);
for(Binding binding : bindings) { for (Binding binding : bindings) {
if(!binding.enabled) { if (!binding.enabled) {
continue; continue;
} }
final String formula = binding.formula; final String formula = binding.formula;
int formula_length = formula.length(); int formula_length = formula.length();
if(formula_length == 0) { if (formula_length == 0) {
continue; continue;
} }
final String field = binding.target; final String field = binding.target;
if(field == null || field.length() == 0) { if (field == null || field.length() == 0) {
continue; continue;
} }
@ -473,7 +442,7 @@ public class VariableManager {
} }
if (simple_identifier == null) { if (simple_identifier == null) {
// this is a function, convert it to a script and extract variable names // 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 // create a script from this
Script script = sm.createScriptForBinding(itemView, binding); Script script = sm.createScriptForBinding(itemView, binding);
@ -485,14 +454,14 @@ public class VariableManager {
target = addTarget(itemView, field, new String[]{simple_identifier}, null); target = addTarget(itemView, field, new String[]{simple_identifier}, null);
} }
if(apply) { if (apply) {
computeTarget(target, fromScreen); computeTarget(target, fromScreen);
targets.add(target); targets.add(target);
} }
} }
// apply new values // apply new values
if(apply) { if (apply) {
applyTargets(targets); applyTargets(targets);
} }
} }
@ -500,34 +469,21 @@ public class VariableManager {
private Target addTarget(ItemView itemView, String field, String[] variable_names, Script script) { private Target addTarget(ItemView itemView, String field, String[] variable_names, Script script) {
int l = variable_names.length; int l = variable_names.length;
Variable[] variables = new Variable[l]; 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]); variables[i] = getVariable(variable_names[i]);
} }
Target target = new Target(itemView, field, variables, script); Target target = new Target(itemView, field, variables, script);
for(Variable v : variables) { for (Variable v : variables) {
getTargetsForVariable(v.name).add(target); getTargetsForVariable(v.name).add(target);
} }
return 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) { private ArrayList<Target> getTargetsForVariable(String name) {
ArrayList<Target> targets = mVariableTargets.get(name); ArrayList<Target> targets = mVariableTargets.get(name);
if(targets == null) { if (targets == null) {
targets = new ArrayList<>(); targets = new ArrayList<>();
mVariableTargets.put(name, targets); mVariableTargets.put(name, targets);
} }
@ -535,31 +491,82 @@ public class VariableManager {
} }
private void computeTarget(Target target, Screen fromScreen) { private void computeTarget(Target target, Screen fromScreen) {
if(target.script == null) { if (target.script == null) {
target.value = target.variables[0].value; target.value = target.variables[0].value;
} else { } else {
int l = target.variables.length; int l = target.variables.length;
Object[] arguments = new Object[l+2]; Object[] arguments = new Object[l + 2];
mTmpStringBuilder.setLength(0); mTmpStringBuilder.setLength(0);
mTmpStringBuilder.append("item,target"); mTmpStringBuilder.append("item,target");
// TODO not sure whether this is really efficient, can it be optimized? // TODO not sure whether this is really efficient, can it be optimized?
ScriptExecutor se = mEngine.getScriptExecutor(); ScriptExecutor se = mEngine.getScriptExecutor();
Lightning ll = se.getLightning(); Lightning ll = se.getLightning();
arguments[0] = ll.getCachedItem(target.itemView); arguments[0] = ll.getCachedItem(target.itemView);
arguments[1] = target.field; arguments[1] = target.field;
for(int i=0; i<l; i++) { for (int i = 0; i < l; i++) {
Variable variable = target.variables[i]; Variable variable = target.variables[i];
arguments[i+2] = variable.value; arguments[i + 2] = variable.value;
mTmpStringBuilder.append(','); mTmpStringBuilder.append(',');
mTmpStringBuilder.append(variable.name); mTmpStringBuilder.append(variable.name);
} }
Object result = se.runScriptAsFunction(fromScreen, target.script.id, mTmpStringBuilder.toString(), arguments, false, true); Object result = se.runScriptAsFunction(fromScreen, target.script.id, mTmpStringBuilder.toString(), arguments, false, true);
if(result != null) { if (result != null) {
target.value = result; target.value = result;
} }
} }
target.dateComputed = mDate; 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.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.provider.Settings; import android.provider.Settings;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
@ -114,7 +112,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
lightningEngine.registerGlobalConfigChangeListener(this); lightningEngine.registerGlobalConfigChangeListener(this);
final GlobalConfig globalConfig = lightningEngine.getGlobalConfig(); final GlobalConfig globalConfig = lightningEngine.getGlobalConfig();
mOverlayScreen = globalConfig.overlayScreen; mOverlayScreen = globalConfig.overlayScreen;
mOverlayShowHandlePosition =globalConfig.overlayShowHandlePosition; mOverlayShowHandlePosition = globalConfig.overlayShowHandlePosition;
mOverlayShowHandleSize = globalConfig.overlayShowHandleSize; mOverlayShowHandleSize = globalConfig.overlayShowHandleSize;
mOverlayShowHandleWidth = globalConfig.overlayShowHandleWidth; mOverlayShowHandleWidth = globalConfig.overlayShowHandleWidth;
mOverlayHideHandlePosition = globalConfig.overlayHideHandlePosition; mOverlayHideHandlePosition = globalConfig.overlayHideHandlePosition;
@ -131,7 +129,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
public boolean onKey(View v, int keyCode, KeyEvent event) { public boolean onKey(View v, int keyCode, KeyEvent event) {
int action = event.getAction(); int action = event.getAction();
if (keyCode == KeyEvent.KEYCODE_MENU) { if (keyCode == KeyEvent.KEYCODE_MENU) {
if(action == KeyEvent.ACTION_UP) { if (action == KeyEvent.ACTION_UP) {
EventAction ea = mMainPage.config.menuKey; EventAction ea = mMainPage.config.menuKey;
if (ea.action == GlobalConfig.UNSET) { if (ea.action == GlobalConfig.UNSET) {
ea = globalConfig.menuKey; ea = globalConfig.menuKey;
@ -140,13 +138,13 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
} }
return true; return true;
} else if (keyCode == KeyEvent.KEYCODE_BACK) { } else if (keyCode == KeyEvent.KEYCODE_BACK) {
if(action == KeyEvent.ACTION_UP) { if (action == KeyEvent.ACTION_UP) {
FolderView fv = mScreen.findTopmostFolderView(); FolderView fv = mScreen.findTopmostFolderView();
if (fv != null) { if (fv != null) {
mScreen.closeFolder(fv, true); mScreen.closeFolder(fv, true);
} else { } else {
EventAction ea = mMainPage.config.backKey; EventAction ea = mMainPage.config.backKey;
if(ea.action == GlobalConfig.UNSET) { if (ea.action == GlobalConfig.UNSET) {
hideWorkspace(); hideWorkspace();
} else { } else {
mScreen.runAction(mMainPage.getEngine(), "K_BACK", ea); 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 = mContentView.findViewById(R.id.hide_handle);
mHideHandle.setVisibility(View.GONE); mHideHandle.setVisibility(View.GONE);
mItemLayout=(ItemLayout) mWorkspaceView.findViewById(R.id.window_il); mItemLayout = mWorkspaceView.findViewById(R.id.window_il);
mScreen.takeItemLayoutOwnership(mItemLayout); mScreen.takeItemLayoutOwnership(mItemLayout);
mItemLayout.setHonourFocusChange(false); mItemLayout.setHonourFocusChange(false);
int windowType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; int windowType = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams( WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 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_NOT_TOUCH_MODAL
// |WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN // |WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
// |WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE // |WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE
|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES | WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|0, | 0,
PixelFormat.TRANSLUCENT); PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.LEFT | Gravity.TOP; lp.gravity = Gravity.LEFT | Gravity.TOP;
// mWindowManager.addView(mContentView, lp); // 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"); Class PolicyManager = getClass().getClassLoader().loadClass("com.android.internal.policy.PolicyManager");
Method m = PolicyManager.getMethod("makeNewWindow", Context.class); Method m = PolicyManager.getMethod("makeNewWindow", Context.class);
mWindow = (Window) m.invoke(null, this); mWindow = (Window) m.invoke(null, this);
} catch(ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// starting at Android 6 // starting at Android 6
Class PhoneWindow = getClass().getClassLoader().loadClass("com.android.internal.policy.PhoneWindow"); Class PhoneWindow = getClass().getClassLoader().loadClass("com.android.internal.policy.PhoneWindow");
mWindow = (Window) PhoneWindow.getDeclaredConstructor(Context.class).newInstance(this); mWindow = (Window) PhoneWindow.getDeclaredConstructor(Context.class).newInstance(this);
@ -380,7 +378,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null) { if (intent != null) {
String action = intent.getAction(); String action = intent.getAction();
if (INTENT_ACTION_SHOW.equals(action)) { if (INTENT_ACTION_SHOW.equals(action)) {
showWorkspace(); showWorkspace();
@ -394,7 +392,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override @Override
public final Resources getResources() { public final Resources getResources() {
if(mResourcesWrapperHelper == null) { if (mResourcesWrapperHelper == null) {
mResourcesWrapperHelper = new ResourcesWrapperHelper(this, super.getResources()); mResourcesWrapperHelper = new ResourcesWrapperHelper(this, super.getResources());
} }
return mResourcesWrapperHelper.getResources(); return mResourcesWrapperHelper.getResources();
@ -416,12 +414,12 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override @Override
public void onGlobalConfigChanged(GlobalConfig newGlobalConfig) { public void onGlobalConfigChanged(GlobalConfig newGlobalConfig) {
if(newGlobalConfig.overlayScreen != mOverlayScreen) { if (newGlobalConfig.overlayScreen != mOverlayScreen) {
mOverlayScreen = newGlobalConfig.overlayScreen; mOverlayScreen = newGlobalConfig.overlayScreen;
configurePage(); configurePage();
} }
if(newGlobalConfig.overlayAnimation != mOverlayAnimation || if (newGlobalConfig.overlayAnimation != mOverlayAnimation ||
newGlobalConfig.overlayShowHandlePosition != mOverlayShowHandlePosition || newGlobalConfig.overlayShowHandlePosition != mOverlayShowHandlePosition ||
newGlobalConfig.overlayShowHandleSize != mOverlayShowHandleSize || newGlobalConfig.overlayShowHandleSize != mOverlayShowHandleSize ||
newGlobalConfig.overlayShowHandleWidth != mOverlayShowHandleWidth || newGlobalConfig.overlayShowHandleWidth != mOverlayShowHandleWidth ||
@ -546,8 +544,8 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mShowHandle.setBackgroundColor(mOverlayDisplayHandles ? 0x8000a000 : 0); mShowHandle.setBackgroundColor(mOverlayDisplayHandles ? 0x8000a000 : 0);
mHideHandle.setBackgroundColor(mOverlayDisplayHandles ? 0x80a00000 : 0); mHideHandle.setBackgroundColor(mOverlayDisplayHandles ? 0x80a00000 : 0);
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams)mWindow.getDecorView().getLayoutParams()); WindowManager.LayoutParams lp = ((WindowManager.LayoutParams) mWindow.getDecorView().getLayoutParams());
lp.gravity = ((FrameLayout.LayoutParams)mShowHandle.getLayoutParams()).gravity; lp.gravity = ((FrameLayout.LayoutParams) mShowHandle.getLayoutParams()).gravity;
mWindowManager.updateViewLayout(mWindow.getDecorView(), lp); mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
// mWindow.setGravity(((FrameLayout.LayoutParams)mShowHandle.getLayoutParams()).gravity); // mWindow.setGravity(((FrameLayout.LayoutParams)mShowHandle.getLayoutParams()).gravity);
@ -827,20 +825,28 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mWorkspaceView.setTranslationX(0); mWorkspaceView.setTranslationX(0);
mWorkspaceView.setTranslationY(0); mWorkspaceView.setTranslationY(0);
if(mOverlayAnimation == GlobalConfig.OverlayAnimation.SLIDE) { if (mOverlayAnimation == GlobalConfig.OverlayAnimation.SLIDE) {
boolean visible = mWorkspaceView.getVisibility() == View.VISIBLE; boolean visible = mWorkspaceView.getVisibility() == View.VISIBLE;
switch (mOverlayShowHandlePosition) { switch (mOverlayShowHandlePosition) {
// FIXME I don't understand why X and Y are inverted, as if not everything was rotated at this time // 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); mWorkspaceView.setTranslationX(visible ? 0 : -mScreenWidth);
break; break;
case RIGHT_TOP: case RIGHT_MIDDLE: case RIGHT_BOTTOM: case RIGHT_TOP:
case RIGHT_MIDDLE:
case RIGHT_BOTTOM:
mWorkspaceView.setTranslationX(visible ? 0 : mScreenWidth); mWorkspaceView.setTranslationX(visible ? 0 : mScreenWidth);
break; break;
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT: case TOP_LEFT:
case TOP_CENTER:
case TOP_RIGHT:
mWorkspaceView.setTranslationY(visible ? 0 : -mScreenHeight); mWorkspaceView.setTranslationY(visible ? 0 : -mScreenHeight);
break; break;
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT: case BOTTOM_LEFT:
case BOTTOM_CENTER:
case BOTTOM_RIGHT:
mWorkspaceView.setTranslationY(visible ? 0 : mScreenHeight); mWorkspaceView.setTranslationY(visible ? 0 : mScreenHeight);
break; break;
} }
@ -849,42 +855,58 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
private ViewPropertyAnimator createDrawerAnimation(GlobalConfig.OverlayHandlePosition from, boolean show, long duration) { private ViewPropertyAnimator createDrawerAnimation(GlobalConfig.OverlayHandlePosition from, boolean show, long duration) {
ViewPropertyAnimator animator = mWorkspaceView.animate(); ViewPropertyAnimator animator = mWorkspaceView.animate();
if(show) { if (show) {
if(mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) { if (mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) {
animator.alpha(1); animator.alpha(1);
} else { } else {
switch (from) { switch (from) {
case LEFT_TOP: case LEFT_MIDDLE: case LEFT_BOTTOM: case LEFT_TOP:
case RIGHT_TOP: case RIGHT_MIDDLE: case RIGHT_BOTTOM: case LEFT_MIDDLE:
case LEFT_BOTTOM:
case RIGHT_TOP:
case RIGHT_MIDDLE:
case RIGHT_BOTTOM:
animator.translationX(0); animator.translationX(0);
break; break;
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT: case TOP_LEFT:
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT: case TOP_CENTER:
case TOP_RIGHT:
case BOTTOM_LEFT:
case BOTTOM_CENTER:
case BOTTOM_RIGHT:
animator.translationY(0); animator.translationY(0);
break; break;
} }
} }
} else { } else {
if(mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) { if (mOverlayAnimation == GlobalConfig.OverlayAnimation.FADE) {
animator.alpha(0); animator.alpha(0);
} else { } else {
boolean is_show_handle = from == mOverlayShowHandlePosition; boolean is_show_handle = from == mOverlayShowHandlePosition;
switch (from) { switch (from) {
case LEFT_TOP: case LEFT_MIDDLE: case LEFT_BOTTOM: case LEFT_TOP:
animator.translationX(is_show_handle ? -mScreenWidth-1 : mScreenWidth+1); case LEFT_MIDDLE:
case LEFT_BOTTOM:
animator.translationX(is_show_handle ? -mScreenWidth - 1 : mScreenWidth + 1);
break; break;
case RIGHT_TOP: case RIGHT_MIDDLE: case RIGHT_BOTTOM: case RIGHT_TOP:
animator.translationX(is_show_handle ? mScreenWidth+1 : -mScreenWidth-1); case RIGHT_MIDDLE:
case RIGHT_BOTTOM:
animator.translationX(is_show_handle ? mScreenWidth + 1 : -mScreenWidth - 1);
break; break;
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT: case TOP_LEFT:
animator.translationY(is_show_handle ? -mScreenHeight-1 : mScreenHeight+1); case TOP_CENTER:
case TOP_RIGHT:
animator.translationY(is_show_handle ? -mScreenHeight - 1 : mScreenHeight + 1);
break; break;
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT: case BOTTOM_LEFT:
animator.translationY(is_show_handle ? mScreenHeight+1 : -mScreenHeight-1); case BOTTOM_CENTER:
case BOTTOM_RIGHT:
animator.translationY(is_show_handle ? mScreenHeight + 1 : -mScreenHeight - 1);
break; break;
} }
} }
@ -922,7 +944,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
public void onAnimationEnd(Animator animator) { public void onAnimationEnd(Animator animator) {
mWorkspaceView.setTranslationX(0); mWorkspaceView.setTranslationX(0);
WindowManager.LayoutParams lp = ((WindowManager.LayoutParams)mWindow.getDecorView().getLayoutParams()); WindowManager.LayoutParams lp = ((WindowManager.LayoutParams) mWindow.getDecorView().getLayoutParams());
lp.flags = 0; lp.flags = 0;
mWindowManager.updateViewLayout(mWindow.getDecorView(), lp); mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
@ -955,7 +977,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
mShowHandle.setVisibility(View.VISIBLE); mShowHandle.setVisibility(View.VISIBLE);
mHideHandle.setVisibility(View.GONE); 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; lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowManager.updateViewLayout(mWindow.getDecorView(), lp); mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
@ -975,14 +997,14 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
} }
protected void showWorkspace() { protected void showWorkspace() {
if(!mIsShown) { if (!mIsShown) {
overlayIsShown(); overlayIsShown();
showWorkspace(mOverlayShowHandlePosition, true, OPEN_CLOSE_ANIMATION_DURATION); showWorkspace(mOverlayShowHandlePosition, true, OPEN_CLOSE_ANIMATION_DURATION);
} }
} }
protected void hideWorkspace() { protected void hideWorkspace() {
if(mIsShown) { if (mIsShown) {
overlayIsHidden(); overlayIsHidden();
hideWorkspace(mOverlayHideHandlePosition, true, OPEN_CLOSE_ANIMATION_DURATION); hideWorkspace(mOverlayHideHandlePosition, true, OPEN_CLOSE_ANIMATION_DURATION);
} }
@ -1005,7 +1027,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override @Override
public ItemLayout loadRootItemLayout(int page, boolean reset_navigation_history, boolean displayImmediately, boolean animate) { 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; return mItemLayout;
} else { } else {
return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate); return loadRootItemLayoutOffscreen(page, reset_navigation_history, displayImmediately, animate);
@ -1020,7 +1042,7 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
@Override @Override
protected void launchIntent(Intent intent, ItemView itemView) { protected void launchIntent(Intent intent, ItemView itemView) {
super.launchIntent(intent, itemView); super.launchIntent(intent, itemView);
if(LLApp.get().getAppEngine().getGlobalConfig().overlayLaunchHide) { if (LLApp.get().getAppEngine().getGlobalConfig().overlayLaunchHide) {
hideWorkspace(); hideWorkspace();
} }

View file

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

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