Merge branch '14.3-beta7'

This commit is contained in:
Pierrot 2019-06-24 09:12:41 +02:00
commit f9f429442d
109 changed files with 2417 additions and 792 deletions

View file

@ -16,6 +16,20 @@ javadoc \
sed -i 's/getEvent_/getEvent/g' html/reference/net/pierrox/lightning_launcher/script/api/Lightning.html
sed -i 's/getEvent_/getEvent/g' html/reference/net/pierrox/lightning_launcher/script/api/LL.html
sed -i 's/getEvent_/getEvent/g' html/reference/net/pierrox/lightning_launcher/script/api/Event.html
sed -i 's/getEvent_/getEvent/g' html/reference/current.xml
scp -r html pierrot@ruby:~/tmp
echo "beta? y/n [n]"
read answer
if [ "$answer" = "y" ]; then
dir=api-beta
else
dir=api
fi
rm -rf llx-$dir
cp -r html llx-$dir
tar czf llx-$dir.tar.gz llx-$dir
scp llx-$dir.tar.gz pierrot@vmail:/home/www/lightninglauncher.com/docs/www/scripting/reference/downloadable
ssh pierrot@vmail "cd /home/www/lightninglauncher.com/docs/www/scripting/reference && rm -rf $dir && tar xf downloadable/llx-$dir.tar.gz && mv llx-$dir $dir"
rm -rf llx-$dir.tar.gz llx-$dir

View file

@ -3,8 +3,8 @@
<h1>Lightning Launcher Scripting API</h1>
<h2>Introduction</h2>
<p>Starting at version 10 (alpha 9.9), Lightning Launcher has support for extending its behavior through JavaScript. This is an advanced and extremly powerful feature, and for this reason it requires some care.</p>
<p>The description of LL script APIs can be found here {@link net.pierrox.lightning_launcher.script.api}. The {@link LL} objet is the entry point for most things.</p>
<p>Starting at version 10 (alpha 9.9), Lightning Launcher has support for extending its behavior through JavaScript. This is an advanced and extremely powerful feature, and for this reason it requires some care.</p>
<p>The description of LL script APIs can be found here {@link net.pierrox.lightning_launcher.script.api}. The {@link LL} object is the entry point for most things.</p>
<h2>Available Android classes</h2>
<p>Some Android classes can be directly used through scripting (creation of new instances, access to static fields - aka constants - and method calls). The list of supported classes are:
@ -35,26 +35,26 @@
<li>TaskerIntent</li>
<li>ActionCodes</li>
</ul>
Other classes can be accessed through their fully qualified name. For instance, should you need to access accelerometers, you may want to use <code>android.hardware.Sensor.TYPE_ACCELEROMETER</code>. Using <code>LL.bindClass(String name)</code> will conveniently suppress the need for explicit package naming (<code>Sensor.TYPE_ACCELEROMETER</code> would be enough if <code>LL.bindClass("android.hardware.Sensor");</code> has been called previously.
Other classes can be accessed through their fully qualified name. For instance, should you need to access accelerometers, you may want to use <code>android.hardware.Sensor.TYPE_ACCELEROMETER</code>. Using <code>bindClass(String name)</code> will conveniently suppress the need for explicit package naming (<code>Sensor.TYPE_ACCELEROMETER</code> would be enough if <code>bindClass("android.hardware.Sensor");</code> has been called previously.
</p>
<h2>Things to be aware of</h2>
<p>Use the new Script Editor icon (in your app drawer) to quickly edit scripts. No need to configure events and select run a script: just launch the script editor and it will open on the last edited script.</p>
<h2>DOs and DON'Ts</h2>
<h3>Use and absuse from variables</h3>
<h3>Use and abuse from variables</h3>
<p>API calls are expensive, and you never know what is hidden behind. It is a good idea to keep return values in local variables to minimize API calls. For instance:
<pre>
alert(LL.getEvent().getTouchX()+" / "+LL.getEvent().getTouchY()); /* BAD */
alert(getEvent().getTouchX()+" / "+getEvent().getTouchY()); /* BAD */
var e = LL.getEvent();
var e = getEvent();
alert(e.getTouchX()+" / "+e.getTouchY()); /* BETTER */
</pre>
</p>
<h3>Not suitable for (smooth) animations</h3>
<p>While it is possible to move, rotate or change items configuration, performances may not be enough to sustain a 60Hz animation rate.</p>
<h3>Timers</h3>
<p>It is possible to set timers using setTimeout. Pay special attention to clear these timers when needed, LL won't do this for you. If you don't clear timers, you may severly increase CPU use and battery consumption.</p>
<p>It is possible to set timers using setTimeout. Pay special attention to clear these timers when needed, LL won't do this for you. If you don't clear timers, you may severely increase CPU use and battery consumption.</p>
<h3>Object references</h3>
<p>Avoid keeping references to objects returned by LL APIs in the script side, otherwise you may leak data. It is possible to use <pre>self</pre> to store data that are kept between two script execution (and can be shared between scripts), but try to avoid this as much as possible.</p>

View file

@ -42,16 +42,16 @@ if(project.hasProperty("signing.properties") && new File(project.property("signi
}
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
compileSdkVersion 28
defaultConfig {
versionCode 325
versionName "14.3-beta3 (ec5b56b)"
versionCode 328
versionName "14.3-beta7 (x)"
buildConfigField "boolean", "IS_BETA", "true" // change in core too
buildConfigField "boolean", "HAS_UEC", "false"
minSdkVersion 14
targetSdkVersion 26
targetSdkVersion 28
}
// dexOptions {

View file

@ -14,9 +14,10 @@
<!-- direct dial shortcuts -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<!-- app killer -->
<!-- apps management -->
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<!-- messaging related -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
@ -28,8 +29,10 @@
<uses-permission android:name="net.dinglisch.android.tasker.PERMISSION_RUN_TASKS"/>
<permission
android:name="net.pierrox.lightning_launcher.USE_PLUGIN_SERVICE"
android:protectionLevel="dangerous"/>
android:name="net.pierrox.lightning_launcher.USE_SCRIPT_SERVICE"
android:protectionLevel="dangerous"
android:label="@string/permission_label"
android:description="@string/permission_description"/>
<supports-screens
@ -356,8 +359,8 @@
</intent-filter>
</activity>
<service android:name="net.pierrox.lightning_launcher.util.PluginService"
android:permission="net.pierrox.lightning_launcher.USE_PLUGIN_SERVICE"
<service android:name="net.pierrox.lightning_launcher.util.ScriptService"
android:permission="net.pierrox.lightning_launcher.USE_SCRIPT_SERVICE"
android:exported="true"/>
</application>

View file

@ -1,25 +0,0 @@
package net.pierrox.lightning_launcher.plugin;
interface IPluginService {
/**
* @returns id of the newly created script, or -1 if the name/path combination already exists
*/
int createScript(String code, String name, String path, int flags);
/**
* @returns id of the newly created or overwritten script
*/
int createOrOverwriteScript(String code, String name, String path, int flags);
/**
* runs the script with the given id and optional data
*/
void runScript(int id, String data);
/**
* runs the given code. Code must end with a return statement
*/
String runCode(String code);
}

View file

@ -535,6 +535,20 @@ public class AdvancedEditText extends EditText implements OnKeyListener, OnGestu
}
}
/**
* 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 */

View file

@ -11,6 +11,7 @@ import net.pierrox.lightning_launcher.activities.AppDrawerX;
import net.pierrox.lightning_launcher.activities.Dashboard;
import net.pierrox.lightning_launcher.activities.LockScreen;
import net.pierrox.lightning_launcher.activities.ScriptEditor;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.overlay.WindowService;
@ -132,7 +133,7 @@ public abstract class LLAppPhone extends LLApp {
// FIXME rename this to displayDashboardPage or better
@Override
public void displayPagerPage(int page, boolean reset_navigation_history) {
Screen homeScreen = getScreen(Screen.Identity.HOME);
Screen homeScreen = getScreen(ScreenIdentity.HOME);
if(homeScreen != null) {
homeScreen.loadRootItemLayout(page, reset_navigation_history, true, true);
} else {

View file

@ -40,6 +40,7 @@ import android.widget.Toast;
import android.widget.ViewAnimator;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.configuration.ItemConfig;
import net.pierrox.lightning_launcher.configuration.PageConfig;
@ -1682,8 +1683,8 @@ public class AppDrawerX extends Dashboard implements EditTextIme.OnEditTextImeLi
}
@Override
public Identity getIdentity() {
return Identity.APP_DRAWER;
public ScreenIdentity getIdentity() {
return ScreenIdentity.APP_DRAWER;
}
@Override

View file

@ -242,7 +242,6 @@ public class ApplyTemplate extends ResourceWrapperActivity {
cb_wallpaper.setText(R.string.tmpl_w);
builder.setView(content);
builder.setMessage(getString(R.string.apply_tmpl_m, mTemplateDisplayName));
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

View file

@ -2,6 +2,7 @@ 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;
@ -20,13 +21,14 @@ 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.engine.LightningEngine;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.util.FileProvider;
import net.pierrox.lightning_launcher_extreme.R;
import org.json.JSONObject;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
@ -36,10 +38,12 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Rect;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
@ -60,6 +64,8 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
private static final int DIALOG_CONFIRM_DELETE=6;
private static final int REQUEST_SELECT_PAGES_FOR_EXPORT = 1;
private static final int REQUEST_SELECT_FILE_TO_IMPORT = 2;
private static final int REQUEST_SELECT_FILE_TO_LOAD = 3;
private ListView mListView;
private TextView mEmptyView;
@ -80,6 +86,11 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
backup.setText(R.string.backup_t);
backup.setOnClickListener(this);
Button import_ = (Button) findViewById(R.id.import_);
import_.setText(R.string.import_t);
import_.setOnClickListener(this);
import_.setOnLongClickListener(this);
Button export = (Button) findViewById(R.id.export);
export.setText(R.string.tmpl_e_t);
export.setOnClickListener(this);
@ -161,6 +172,10 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
exportArchive(true);
break;
case R.id.import_:
selectFileToLoadOrImport(true);
break;
case R.id.export:
exportArchive(false);
break;
@ -168,9 +183,17 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
}
@Override
public boolean onLongClick(View arg0) {
public boolean onLongClick(View view) {
switch(view.getId()) {
case R.id.export:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.pierrox.net/cmsms/applications/lightning-launcher/templates.html")));
return true;
case R.id.import_:
selectFileToLoadOrImport(false);
return true;
}
return false;
}
@Override
@ -234,7 +257,7 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
if(mArchiveName != null || mArchiveUri != null) {
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.br_rc);
builder.setMessage(mArchiveName==null ? mArchiveUri.getLastPathSegment() : mArchiveName);
builder.setMessage(mArchiveName==null ? getNameForUri(mArchiveUri) : mArchiveName);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
@ -297,8 +320,10 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
case 3:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName)));
Uri uri = FileProvider.getUriForFile(new File(FileUtils.LL_EXT_DIR +"/"+mArchiveName));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("application/zip");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.br_s)));
break;
case 4:
@ -359,6 +384,14 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
doExportTemplate(mArchiveName, all_pages);
}
} else if(requestCode == REQUEST_SELECT_FILE_TO_IMPORT){
if(resultCode == RESULT_OK) {
importFile(data.getData());
}
} else if(requestCode == REQUEST_SELECT_FILE_TO_LOAD){
if(resultCode == RESULT_OK) {
loadArchive(data.getData(), null);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
@ -570,4 +603,83 @@ public class BackupRestore extends ResourceWrapperActivity implements View.OnCli
}
}
}
/**
* Request the user to pick an archive.
* @param only_load true to directly load the archive without first importing it in the LL_EXT_DIR directory.
*/
private void selectFileToLoadOrImport(boolean only_load) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, getString(R.string.import_t)), only_load ? REQUEST_SELECT_FILE_TO_LOAD : REQUEST_SELECT_FILE_TO_IMPORT);
}
@SuppressLint("StaticFieldLeak")
private void importFile(final Uri uri) {
new AsyncTask<Void, Void, File>() {
private ProgressDialog mDialog;
@Override
protected void onPreExecute() {
mDialog = new ProgressDialog(BackupRestore.this);
mDialog.setMessage(getString(R.string.importing));
mDialog.setCancelable(false);
mDialog.show();
}
@Override
protected File doInBackground(Void... voids) {
InputStream is = null;
FileOutputStream os = null;
File outFile = null;
try {
String name = getNameForUri(uri);
outFile = new File(FileUtils.LL_EXT_DIR, name);
is = getContentResolver().openInputStream(uri);
os = new FileOutputStream(outFile);
FileUtils.copyStream(is, os);
return outFile;
} catch (IOException e) {
if(outFile != null) {
outFile.delete();
}
return null;
} finally {
try { if(is != null) is.close(); } catch(IOException e) {}
try { if(os != null) os.close(); } catch(IOException e) {}
}
}
@Override
protected void onPostExecute(File outFile) {
mDialog.dismiss();
if(outFile != null) {
loadArchivesList();
loadArchive(null, outFile.getName());
} else {
Toast.makeText(BackupRestore.this, R.string.import_e, Toast.LENGTH_SHORT).show();
}
}
}.execute((Void) null);
}
private String getNameForUri(Uri uri) {
String name = null;
if (uri.getScheme().equals("content")) {
Cursor cursor = getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
}
if (name == null) {
name = uri.getLastPathSegment();
}
return name;
}
}

View file

@ -33,6 +33,7 @@ import com.readystatesoftware.systembartint.SystemBarTintManager;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.Version;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.FolderConfig;
import net.pierrox.lightning_launcher.configuration.FolderConfig.FolderAnimation;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
@ -247,8 +248,8 @@ public class Customize extends ResourceWrapperActivity implements
} else {
mScreen = new Screen(this, 0) {
@Override
public Identity getIdentity() {
return Identity.CUSTOMIZE;
public ScreenIdentity getIdentity() {
return ScreenIdentity.CUSTOMIZE;
}
@Override
@ -518,7 +519,7 @@ public class Customize extends ResourceWrapperActivity implements
} else if (preference == mPGReset) {
displayDialog(DIALOG_CONFIRM_RESET_PAGE);
} else if (preference == mPGBackgroundSelectSystemWallpaper) {
startActivity(Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER), getString(R.string.wp_select_t)));
startActivity(Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER), getString(R.string.bg_sys_wp_select_t)));
} else if (preference == mPGBackgroundSelectScreenWallpaper) {
ImagePicker.startActivity(this, REQUEST_PICK_SCREEN_WALLPAPER);
} else if (preference == mPGApplyIconPack) {
@ -1189,11 +1190,17 @@ public class Customize extends ResourceWrapperActivity implements
if (Build.VERSION.SDK_INT >= 19) {
mPreferencesPageSystemBars.add(mPGSystemBarsStatusBarColor = new LLPreferenceColor(this, ID_mPGSystemBarsStatusBarColor, R.string.sbc_t, 0, pc.statusBarColor, null, true));
if (Build.VERSION.SDK_INT >= 23) {
mPreferencesPageSystemBars.add(mPGSystemBarsStatusBarLight = new LLPreferenceCheckBox(this, ID_mPGSystemBarsStatusBarLight, R.string.sbl_t, 0, pc.statusBarLight, null));
}
mPreferencesPageSystemBars.add(mPGSystemBarsStatusBarOverlap = new LLPreferenceCheckBox(this, ID_mPGSystemBarsStatusBarOverlap, R.string.sbo_t, 0, pc.statusBarOverlap, null));
if (mSystemBarTintManager == null || (mSystemBarTintManager != null && mSystemBarTintManager.getConfig().hasNavigationBar())) {
mPreferencesPageSystemBars.add(new LLPreferenceCategory(this, R.string.nb_c));
mPreferencesPageSystemBars.add(mPGSystemBarsNavigationBarColor = new LLPreferenceColor(this, ID_mPGSystemBarsNavigationBarColor, R.string.nbc_t, 0, pc.navigationBarColor, null, true));
if (Build.VERSION.SDK_INT >= 26) {
mPreferencesPageSystemBars.add(mPGSystemBarsNavigationBarLight = new LLPreferenceCheckBox(this, ID_mPGSystemBarsNavigationBarLight, R.string.nbl_t, 0, pc.navigationBarLight, null));
}
mPreferencesPageSystemBars.add(mPGSystemBarsNavBarOverlap = new LLPreferenceCheckBox(this, ID_mPGSystemBarsNavBarOverlap, R.string.nbo_t, 0, pc.navigationBarOverlap, null));
}
}
@ -1310,6 +1317,7 @@ public class Customize extends ResourceWrapperActivity implements
is_folder_page ? R.string.this_folder_feel_t
: R.string.folder_feel_t, R.string.folder_feel_s));
mPreferencesPageFolderFeel = new ArrayList<LLPreference>();
mPreferencesPageFolderFeel.add(mPGFolderFeelOutsideTapClose = new LLPreferenceCheckBox(this, ID_mPGFolderFeelOutsideTapClose, R.string.otc_t, 0, fc.outsideTapClose, fc_def == null ? null : fc_def.outsideTapClose));
mPreferencesPageFolderFeel.add(mPGFolderFeelAutoClose = new LLPreferenceCheckBox(this, ID_mPGFolderFeelAutoClose, R.string.auto_close_t, R.string.auto_close_s, fc.autoClose, fc_def == null ? null : fc_def.autoClose));
if(!is_folder_page) {
mPreferencesPageFolderFeel.add(mPGFolderFeelCloseOther = new LLPreferenceCheckBox(this, ID_mPGFolderFeelCloseOther, R.string.cof_t, R.string.cof_s, fc.closeOther, fc_def == null ? null : fc_def.closeOther));
@ -1636,7 +1644,9 @@ public class Customize extends ResourceWrapperActivity implements
if(mPGSystemBarsStatusBarOverlap != null) pc.statusBarOverlap = mPGSystemBarsStatusBarOverlap.isChecked();
if(mPGSystemBarsNavBarOverlap != null) pc.navigationBarOverlap = mPGSystemBarsNavBarOverlap.isChecked();
if(mPGSystemBarsStatusBarColor != null) pc.statusBarColor = mPGSystemBarsStatusBarColor.getColor();
if(mPGSystemBarsStatusBarLight != null) pc.statusBarLight = mPGSystemBarsStatusBarLight.isChecked();
if(mPGSystemBarsNavigationBarColor != null) pc.navigationBarColor = mPGSystemBarsNavigationBarColor.getColor();
if(mPGSystemBarsNavigationBarLight != null) pc.navigationBarLight = mPGSystemBarsNavigationBarLight.isChecked();
pc.statusBarHide = mPGSystemBarsHideStatusBar.isChecked();
if(is_app_drawer) {
pc.autoExit = mPGMiscAutoExit.isChecked();
@ -1660,6 +1670,7 @@ public class Customize extends ResourceWrapperActivity implements
fc.animationIn = (FolderAnimation) mPGFolderLookAnimOpen.getValueEnum();
fc.animationOut = (FolderAnimation) mPGFolderLookAnimClose.getValueEnum();
fc.animFade = mPGFolderLookAnimFade.isChecked();
fc.outsideTapClose = mPGFolderFeelOutsideTapClose.isChecked();
fc.autoClose = mPGFolderFeelAutoClose.isChecked();
if(!is_folder) {
fc.closeOther = mPGFolderFeelCloseOther.isChecked();
@ -2099,7 +2110,9 @@ public class Customize extends ResourceWrapperActivity implements
private LLPreferenceCheckBox mPGSystemBarsStatusBarOverlap;
private LLPreferenceCheckBox mPGSystemBarsNavBarOverlap;
private LLPreferenceColor mPGSystemBarsStatusBarColor;
private LLPreferenceCheckBox mPGSystemBarsStatusBarLight;
private LLPreferenceColor mPGSystemBarsNavigationBarColor;
private LLPreferenceCheckBox mPGSystemBarsNavigationBarLight;
private LLPreferenceColor mPGAppDrawerABTextColor;
private LLPreference mPGAppDrawerABBackground;
@ -2163,6 +2176,7 @@ public class Customize extends ResourceWrapperActivity implements
private LLPreferenceEventAction mPageEventMenu;
private LLPreference mPGFolderFeel;
private LLPreferenceCheckBox mPGFolderFeelOutsideTapClose;
private LLPreferenceCheckBox mPGFolderFeelAutoClose;
private LLPreferenceCheckBox mPGFolderFeelCloseOther;
private LLPreferenceCheckBox mPGFolderFeelAnimGlitchFix;
@ -2226,6 +2240,7 @@ public class Customize extends ResourceWrapperActivity implements
private static final int ID_mPGZoomScrollDisableDiagonal = 90;
private static final int ID_mPGZoomScrollEnablePinch = 91;
private static final int ID_mPGFolderFeel = 92;
private static final int ID_mPGFolderFeelOutsideTapClose = 515;
private static final int ID_mPGFolderFeelAutoClose = 93;
private static final int ID_mPGFolderFeelAnimGlitchFix = 94;
private static final int ID_mPGMisc = 95;
@ -2276,7 +2291,9 @@ public class Customize extends ResourceWrapperActivity implements
private static final int ID_mPGSystemBarsNavBarOverlap = 164;
private static final int ID_mPGSystemBars = 165;
private static final int ID_mPGSystemBarsStatusBarColor = 166;
private static final int ID_mPGSystemBarsStatusBarLight = 513;
private static final int ID_mPGSystemBarsNavigationBarColor = 167;
private static final int ID_mPGSystemBarsNavigationBarLight = 514;
private static final int ID_mGCAppStyle = 168;
private static final int ID_mPGADCategories = 190;
private static final int ID_mPGBackgroundScaleType = 191;

View file

@ -86,6 +86,7 @@ import com.readystatesoftware.systembartint.SystemBarTintManager;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.Version;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.DynamicTextConfig;
import net.pierrox.lightning_launcher.configuration.FolderConfig;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
@ -525,7 +526,7 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
mUndoStack.setUndoListener(this);
if(BuildConfig.IS_BETA) {
if(BuildConfig.HAS_UEC) {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
@ -862,7 +863,7 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
mScreen.runAction(mEngine, "SHORTCUT", eventAction);
handled = true;
} else {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_PAGE)) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP)) {
mScreen.executeGoToDesktopPositionIntent(intent);
handled = true;
}
@ -944,7 +945,7 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
case REQUEST_SELECT_SHORTCUT_FOR_ADD1:
ComponentName cn = data.getComponent();
if(cn != null && cn.getClassName().endsWith(".activities.ShortcutsS")) {
Intent shortcut = PhoneUtils.createDesktopBookmarkShortcut(this, il, null, null, null);
Intent shortcut = PhoneUtils.createDesktopBookmarkShortcut(this, il, null, null, null, true);
newItem=Utils.addAndroidShortcutFromIntent(this, shortcut, page, mScreen.getLastTouchedAddX(), mScreen.getLastTouchedAddY(), scale);
mUndoStack.storePageAddItem(newItem);
} else {
@ -1761,10 +1762,10 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
if(mNoScriptCounter == 5) {
ScriptManager sm = mEngine.getScriptManager();
Script easter_egg = sm.createScriptForFile(getString(R.string.mi_nost), "/"+getPackageName().replace('.', '/'));
easter_egg.setSourceText("LL.bindClass('android.view.animation.AccelerateDecelerateInterpolator');\n" +
"LL.bindClass('android.view.animation.AnimationUtils');\n" +
easter_egg.setSourceText("bindClass('android.view.animation.AccelerateDecelerateInterpolator');\n" +
"bindClass('android.view.animation.AnimationUtils');\n" +
"\n" +
"var item = LL.getEvent().getItem();\n" +
"var item = getEvent().getItem();\n" +
"\n" +
"var properties = item.getProperties();\n" +
"var was_on_grid = properties.getBoolean('i.onGrid');\n" +
@ -2768,7 +2769,7 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
mHandler.removeCallbacks(mSetLiveWallpaperVisibility);
mSetLiveWallpaperVisibility = null;
}
final Screen lwp = LLApp.get().getScreen(Screen.Identity.LIVE_WALLPAPER);
final Screen lwp = LLApp.get().getScreen(ScreenIdentity.LIVE_WALLPAPER);
if(lwp != null) {
if(delay != 0) {
mSetLiveWallpaperVisibility = new Runnable() {
@ -3281,7 +3282,7 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
private void addBookmark() {
ItemLayout il = mScreen.getTargetOrTopmostItemLayout();
Page page = il.getPage();
Intent intent = PhoneUtils.createDesktopBookmarkShortcut(this, il, null, null, null);
Intent intent = PhoneUtils.createDesktopBookmarkShortcut(this, il, null, null, null, true);
Item item = Utils.addAndroidShortcutFromIntent(this, intent, page, mScreen.getLastTouchedAddX(), mScreen.getLastTouchedAddY(), il.getCurrentScale());
mUndoStack.storePageAddItem(item);
boolean wasInEditMode = il.getEditMode();
@ -3324,25 +3325,12 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
@TargetApi(Build.VERSION_CODES.O)
private void addPinnedShortcut(Intent intent) {
Parcelable extra = intent.getParcelableExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST);
if(extra instanceof LauncherApps.PinItemRequest) {
LauncherApps.PinItemRequest request = (LauncherApps.PinItemRequest) extra;
if (request.getRequestType() == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT) {
final LauncherApps launcherApps = (LauncherApps) getSystemService(LAUNCHER_APPS_SERVICE);
ShortcutInfo shortcutInfo = request.getShortcutInfo();
final Drawable iconDrawable = launcherApps.getShortcutIconDrawable(shortcutInfo, Utils.getLauncherIconDensity());
Bitmap icon = Utils.createBitmapFromDrawable(iconDrawable);
Intent si = new Intent(Shortcut.INTENT_ACTION_APP_SHORTCUT);
si.putExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID, shortcutInfo.getId());
si.putExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG, shortcutInfo.getPackage());
si.putExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_DISABLED_MSG, shortcutInfo.getDisabledMessage());
Utils.ShortcutDescription sd = Utils.createPinItemRequestFromIntent(this, intent);
if(sd != null) {
final ItemLayout il = mScreen.getTargetOrTopmostItemLayout();
Page page = il.getPage();
float scale = il.getCurrentScale();
final Item newItem = Utils.addShortcut(shortcutInfo.getShortLabel().toString(), icon, si, page, Utils.POSITION_AUTO, Utils.POSITION_AUTO, scale, true);
final Item newItem = Utils.addShortcut(sd.name, sd.icon, sd.intent, page, Utils.POSITION_AUTO, Utils.POSITION_AUTO, scale, true);
mUndoStack.storePageAddItem(newItem);
editItem(il, newItem);
@ -3352,9 +3340,6 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
mScreen.ensureItemViewVisible(il.getItemView(newItem), false);
}
}, 1000);
request.accept();
}
}
}
@ -6135,8 +6120,8 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
}
@Override
public Identity getIdentity() {
return Identity.HOME;
public ScreenIdentity getIdentity() {
return ScreenIdentity.HOME;
}
@Override
@ -7378,5 +7363,12 @@ public class Dashboard extends ResourceWrapperActivity implements OnLongClickLis
startActivity(new Intent(Dashboard.this, Dashboard.class));
System.exit(0);
}
@Override
public void onSystemBarsSizeChanged() {
Page page = mScreen.getCurrentRootPage();
if(page != null) {
configureSystemBarsPadding(page.config);
} }
}
}

View file

@ -15,6 +15,7 @@ import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.EventAction;
import net.pierrox.lightning_launcher.data.Item;
@ -221,8 +222,8 @@ public class LockScreen extends Dashboard {
}
@Override
public Identity getIdentity() {
return Identity.LOCK;
public ScreenIdentity getIdentity() {
return ScreenIdentity.LOCK;
}
@Override

View file

@ -39,6 +39,7 @@ import android.widget.Toast;
import net.pierrox.lightning_launcher.API;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.LLAppPhone;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.Item;
import net.pierrox.lightning_launcher.data.LightningIntent;
@ -159,8 +160,8 @@ public class ScreenManager extends ResourceWrapperActivity implements OnClickLis
private void init() {
mScreen = new net.pierrox.lightning_launcher.engine.Screen(this, 0) {
@Override
public Identity getIdentity() {
return Identity.DESKTOP_PREVIEW;
public ScreenIdentity getIdentity() {
return ScreenIdentity.DESKTOP_PREVIEW;
}
@Override
@ -418,7 +419,7 @@ public class ScreenManager extends ResourceWrapperActivity implements OnClickLis
int p = (Integer)v.getTag();
Screen screen = mScreens.get(getScreenIndex(p));
Page page = mLightningEngine.getOrLoadPage(p);
Intent shortcut = PhoneUtils.createDesktopBookmarkShortcut(this, null, page, screen.label, screen.icon);
Intent shortcut = PhoneUtils.createDesktopBookmarkShortcut(this, null, page, screen.label, screen.icon, true);
setResult(RESULT_OK, shortcut);
finish();
} else if(mMode==SCREEN_MODE_SELECT_MULTIPLE) {
@ -636,7 +637,7 @@ public class ScreenManager extends ResourceWrapperActivity implements OnClickLis
Intent intent = s.getIntent();
ComponentName cn=intent.getComponent();
if(cn!=null && cn.compareTo(ll_component_name)==0) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_PAGE) && intent.getIntExtra(LightningIntent.INTENT_EXTRA_PAGE, 0)==screen.page) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP) && intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, 0)==screen.page) {
// it looks like a screen&position shortcut
if(update_icon) {
icon_dir.mkdirs();

View file

@ -24,6 +24,7 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Pair;
import android.util.SparseArray;
import android.view.GestureDetector;
import android.view.KeyEvent;
@ -49,9 +50,8 @@ import net.pierrox.lightning_launcher.Version;
import net.pierrox.lightning_launcher.data.FileUtils;
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.Script;
import net.pierrox.lightning_launcher.script.api.Array;
import net.pierrox.lightning_launcher.script.ScriptManager;
import net.pierrox.lightning_launcher.script.api.Box;
import net.pierrox.lightning_launcher.script.api.Container;
import net.pierrox.lightning_launcher.script.api.Desktop;
@ -64,17 +64,17 @@ import net.pierrox.lightning_launcher.script.api.ImageNinePatch;
import net.pierrox.lightning_launcher.script.api.ImageScript;
import net.pierrox.lightning_launcher.script.api.ImageSvg;
import net.pierrox.lightning_launcher.script.api.Item;
import net.pierrox.lightning_launcher.script.api.LL;
import net.pierrox.lightning_launcher.script.api.Lightning;
import net.pierrox.lightning_launcher.script.api.PageIndicator;
import net.pierrox.lightning_launcher.script.api.Panel;
import net.pierrox.lightning_launcher.script.api.PropertyEditor;
import net.pierrox.lightning_launcher.script.api.PropertySet;
import net.pierrox.lightning_launcher.script.api.RectL;
import net.pierrox.lightning_launcher.script.api.Shortcut;
import net.pierrox.lightning_launcher.script.api.StopPoint;
import net.pierrox.lightning_launcher.util.FileAndDirectoryPickerDialog;
import net.pierrox.lightning_launcher.util.FileProvider;
import net.pierrox.lightning_launcher.util.Indentation;
import net.pierrox.lightning_launcher.util.Search;
import net.pierrox.lightning_launcher_extreme.BuildConfig;
import net.pierrox.lightning_launcher_extreme.R;
@ -100,6 +100,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
private static final String PREF_LAST_SCRIPT_ID = "se_lsi";
private static final String PREF_LAST_SCRIPT_LINE = "se_lsl";
private static final String PREF_WORDWRAP = "se_w";
private static final String PREF_AUTOINDENT = "se_ind";
private static final String PREF_FONT_SIZE = "se_fs";
private static final String PREF_DIRECTORY = "se_d";
private static final String PREF_SUB_DIRS = "se_sd";
@ -123,6 +124,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
private CheckBox mMenuCustom;
private ArrayAdapter<Script> mScriptAdapter;
private List<Script> mAllScripts = new ArrayList<>();
private Indentation mIndentation;
private Search mSearch;
private boolean mShowSubDirs;
@ -240,7 +243,9 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
}
}
private static ArrayList<TokenMethod> sAutoCompleteTokens;
private static TokenClass sLLToken = new TokenClass(LL.class);
private static Token[] sMainTokens = new Token[]{
new TokenMethod(Lightning.class, "getEvent", "void", new Class[0])
};
private Animation mLeftPaneAnimIn;
private Animation mLeftPaneAnimOut;
@ -301,25 +306,27 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
mLeftPaneAnimOut = AnimationUtils.makeOutAnimation(this, false);
// mCompletionsListView = (ListView) findViewById(R.id.completions);
mCompletionsViewGroup = (ViewGroup) findViewById(R.id.completions);
mCompletionsViewGroup = findViewById(R.id.completions);
initializeShortcuts((ViewGroup) findViewById(R.id.shortcuts));
Button btn;
btn = (Button)findViewById(R.id.sc_import);
btn = findViewById(R.id.sc_import);
btn.setOnClickListener(this);
btn.setText(R.string.sc_import);
btn = (Button)findViewById(R.id.sc_new);
btn = findViewById(R.id.sc_new);
btn.setOnClickListener(this);
btn.setText(R.string.sc_new);
btn = (Button)findViewById(R.id.sc_delete);
btn = findViewById(R.id.sc_delete);
btn.setOnClickListener(this);
btn.setText(R.string.sc_delete);
btn = (Button)findViewById(R.id.sc_edit);
btn = findViewById(R.id.sc_edit);
btn.setOnClickListener(this);
btn.setText(R.string.sc_edit);
btn = (Button)findViewById(R.id.sc_help);
btn = findViewById(R.id.sc_help);
btn.setOnClickListener(this);
btn.setText(R.string.sc_help);
btn = (Button)findViewById(R.id.sc_send);
btn = findViewById(R.id.sc_send);
btn.setOnClickListener(this);
btn.setText(R.string.sc_send);
@ -328,20 +335,20 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
((TextView)findViewById(R.id.sc_path)).setText(R.string.sc_path);
((TextView)findViewById(R.id.sc_name)).setText(R.string.sc_name);
mScriptSpinner = (Spinner) findViewById(R.id.sc_spinner);
mScriptSpinner = findViewById(R.id.sc_spinner);
mScriptSpinner.setLongClickable(true);
mScriptSpinner.setOnItemSelectedListener(this);
mScriptSpinner.setAdapter(mScriptAdapter);
updateScriptsSpinner();
btn = (Button)findViewById(R.id.sc_edit_name);
btn = findViewById(R.id.sc_edit_name);
btn.setOnClickListener(this);
btn.setTypeface(LLApp.get().getIconsTypeface());
if(sAutoCompleteTokens == null) {
buildAutoCompleteTokens();
}
mScriptText = (AdvancedEditText) findViewById(R.id.sc_text);
mScriptText = findViewById(R.id.sc_text);
mScriptText.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL));
mScriptText.addTextChangedListener(mScriptTextWatcher);
mScriptText.setListener(new AdvancedEditText.OnAdvancedEditTextEvent() {
@ -376,19 +383,21 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
mScriptText.setTextSize(size);
}
});
mIndentation = new Indentation();
mSearch = new Search(this, mScriptText);
((TextView)findViewById(R.id.sc_ma)).setText(R.string.sc_ma);
((TextView)findViewById(R.id.sc_a)).setText(R.string.sc_a);
((TextView)findViewById(R.id.sc_h)).setText(R.string.sc_h);
mMenuLightning = (CheckBox) findViewById(R.id.sc_ml);
mMenuLightning = findViewById(R.id.sc_ml);
mMenuLightning.setText(R.string.sc_ml);
mMenuItem = (CheckBox) findViewById(R.id.sc_mi);
mMenuItem = findViewById(R.id.sc_mi);
mMenuItem.setText(R.string.sc_mi);
mMenuCustom = (CheckBox) findViewById(R.id.sc_mc);
mMenuCustom = findViewById(R.id.sc_mc);
mMenuCustom.setText(R.string.sc_mc);
mShowSubDirs = mSharedPrefs.getBoolean(PREF_SUB_DIRS, true);
CheckBox showSubDirs = (CheckBox) findViewById(R.id.sc_sd);
CheckBox showSubDirs = findViewById(R.id.sc_sd);
showSubDirs.setText(R.string.sc_all);
showSubDirs.setChecked(mShowSubDirs);
showSubDirs.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@ -403,7 +412,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
}
});
mSelectDirectoryButton = (Button) findViewById(R.id.sc_d);
mSelectDirectoryButton = findViewById(R.id.sc_d);
mSelectDirectoryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -426,13 +435,20 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
boolean wordwrap = mSharedPrefs.getBoolean(PREF_WORDWRAP, true);
mScriptText.setWordWrap(wordwrap);
boolean autoindent = mSharedPrefs.getBoolean(PREF_AUTOINDENT, true);
if(autoindent) mIndentation.register(mScriptText);
float text_size = mSharedPrefs.getFloat(PREF_FONT_SIZE, mScriptText.getTextSize() / mScaledDensity);
mScriptText.setTextSize(text_size);
((TextView)findViewById(R.id.sc_o)).setText(R.string.sc_o);
CheckBox wordwrap_checkbox = (CheckBox) findViewById(R.id.sc_w);
CheckBox wordwrap_checkbox = findViewById(R.id.sc_w);
wordwrap_checkbox.setText(R.string.sc_w);
wordwrap_checkbox.setChecked(wordwrap);
wordwrap_checkbox.setOnCheckedChangeListener(this);
CheckBox autoindent_checkbox = findViewById(R.id.sc_ind);
autoindent_checkbox.setText(R.string.sc_ind);
autoindent_checkbox.setChecked(autoindent);
autoindent_checkbox.setOnCheckedChangeListener(this);
TextPosition position = null;
int sel_start = 0, sel_end = 0;
@ -571,7 +587,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
.putFloat(PREF_FONT_SIZE, mScriptText.getTextSize()/mScaledDensity)
.putString(PREF_DIRECTORY, mCurrentDirectory.getAbsolutePath())
.putBoolean(PREF_SUB_DIRS, mShowSubDirs)
.commit();
.apply();
if(mScript.id >= 0) {
setLastScriptId();
@ -602,7 +618,20 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_TAB) {
if(event.isShiftPressed()){
// Shift tab, decrease indent
Pair<Integer, Integer> selectionI =
Indentation.modifyIndent(mScriptText.getTrueSelectionStart(), mScriptText.getTrueSelectionEnd(), false, mScriptText.getEditableText());
mScriptText.setSelection(selectionI.first, selectionI.second);
}else if(mScriptText.hasSelection()){
// No shift tab && selection, increase indent
Pair<Integer, Integer> selectionI =
Indentation.modifyIndent(mScriptText.getTrueSelectionStart(), mScriptText.getTrueSelectionEnd(), true, mScriptText.getEditableText());
mScriptText.setSelection(selectionI.first, selectionI.second);
}else {
// No shift tab && no selection, add tab char
mScriptText.getText().insert(mScriptText.getSelectionStart(), "\t");
}
return true;
}
return super.onKeyUp(keyCode, event);
@ -619,12 +648,12 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
View content = getLayoutInflater().inflate(R.layout.edit_script_dialog, null);
final EditText nameEditText = (EditText) content.findViewById(R.id.sc_name);
final EditText nameEditText = content.findViewById(R.id.sc_name);
nameEditText.setText(mScript.name);
nameEditText.setSelection(mScript.name.length());
final EditText pathEditText = (EditText) content.findViewById(R.id.sc_path);
final Button pickPathButton = (Button) content.findViewById(R.id.sc_pick_path);
final EditText pathEditText = content.findViewById(R.id.sc_path);
final Button pickPathButton = content.findViewById(R.id.sc_pick_path);
pickPathButton.setTypeface(LLApp.get().getIconsTypeface());
pickPathButton.setOnClickListener(new View.OnClickListener() {
@Override
@ -839,7 +868,16 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
switch (buttonView.getId()) {
case R.id.sc_w:
mScriptText.setWordWrap(isChecked);
mSharedPrefs.edit().putBoolean(PREF_WORDWRAP, isChecked).commit();
mSharedPrefs.edit().putBoolean(PREF_WORDWRAP, isChecked).apply();
break;
case R.id.sc_ind:
// toggled autoindentation
if(isChecked){
mIndentation.register(mScriptText);
} else {
mIndentation.unregister(mScriptText);
}
mSharedPrefs.edit().putBoolean(PREF_AUTOINDENT, isChecked).apply();
break;
}
}
@ -917,8 +955,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
}
private void setLastScriptId() {
mSharedPrefs.edit().putInt(PREF_LAST_SCRIPT_ID, mScript.id).commit();
mSharedPrefs.edit().putInt(PREF_LAST_SCRIPT_LINE, mScriptText.getSelectionLine()).commit();
mSharedPrefs.edit().putInt(PREF_LAST_SCRIPT_ID, mScript.id).apply();
mSharedPrefs.edit().putInt(PREF_LAST_SCRIPT_LINE, mScriptText.getSelectionLine()).apply();
}
private void showLeftPane() {
@ -953,7 +991,6 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
private void buildAutoCompleteTokens() {
sAutoCompleteTokens = new ArrayList<>();
Class<?>[] classes = {
Array.class,
Box.class,
net.pierrox.lightning_launcher.script.api.Binding.class,
Container.class,
@ -967,7 +1004,6 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
ImageScript.class,
ImageSvg.class,
Item.class,
LL.class,
Lightning.class,
Panel.class,
StopPoint.class,
@ -978,7 +1014,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
PropertySet.class,
RectL.class,
net.pierrox.lightning_launcher.script.api.Script.class,
Shortcut.class,
net.pierrox.lightning_launcher.script.api.Shortcut.class,
net.pierrox.lightning_launcher.script.api.Lightning.class,
net.pierrox.lightning_launcher.script.api.Menu.class,
ComponentName.class,
@ -1205,7 +1241,10 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
mCompletionsViewGroup.removeAllViews();
final LayoutInflater inflater = getLayoutInflater();
addSugestion(inflater, sLLToken);
if(completions.isEmpty()) {
// add main Tokens if no others are available
addSugestions(inflater, sMainTokens);
}
for (ArrayList<Token> tokens : completions) {
addSugestion(inflater, tokens);
}
@ -1226,11 +1265,13 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
completions.add(l);
}
private void addSugestion(LayoutInflater inflater, Token token) {
private void addSugestions(LayoutInflater inflater, Token[] tokens) {
for (Token token : tokens) {
ArrayList<Token> l = new ArrayList<>(1);
l.add(token);
addSugestion(inflater, l);
}
}
private void addSugestion(LayoutInflater inflater, ArrayList<Token> tokens) {
Button b = (Button) inflater.inflate(R.layout.sc_btn, null);
@ -1240,4 +1281,187 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic
b.setOnLongClickListener(mCompletionButtonLongClickListener);
mCompletionsViewGroup.addView(b);
}
// -------------- shortcuts --------------------
/**
* Represents a button in the bottom of the editor.
*/
private interface Shortcut {
/**
* Label to display
*/
String getLabel();
/**
* @return true if label is an icon (using LL typeface). False if normal text
*/
boolean isLabelIcon();
/**
* Runned when the button is pressed
*/
void apply(AdvancedEditText editText);
}
/**
* This button will send a key to the editText.
*/
private static class ShortcutKey implements Shortcut {
private int key;
private String label;
ShortcutKey(int key, String iconLabel) {
this.key = key;
this.label = iconLabel;
}
@Override
public String getLabel() {
return label;
}
@Override
public boolean isLabelIcon() {
return true;
}
@Override
public void apply(AdvancedEditText editText) {
editText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
key, 0));
editText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_UP,
key, 0));
}
}
/**
* This button will insert a text before and after the cursor.
*/
private static class ShortcutText implements Shortcut {
private String preText;
private String postText;
ShortcutText(String preText, String postText) {
this.preText = preText;
this.postText = postText;
}
@Override
public String getLabel() {
return preText + "·" + postText;
}
@Override
public boolean isLabelIcon() {
return false;
}
@Override
public void apply(AdvancedEditText editText) {
int start = editText.getTrueSelectionStart();
int end = editText.getTrueSelectionEnd();
editText.getEditableText().replace(start, end, preText+postText);
editText.setSelection(start + preText.length());
}
}
enum SA {
DEC_TAB,
INC_TAB,
SEARCH,
SEARCHN,
}
/**
* This button will trigger an action
*/
private class ShortcutAction implements Shortcut {
private SA action;
ShortcutAction(SA action) {
this.action = action;
}
@Override
public String getLabel() {
switch (action) {
case DEC_TAB:
return "A"; // left arrow with bar
case INC_TAB:
return "D"; // right arrow with bar
case SEARCH:
return "I"; // magnifier glass
case SEARCHN:
return "IC"; // magnifier glass and '>'
}
return "n"; // android icon
}
@Override
public boolean isLabelIcon() {
return true;
}
@Override
public void apply(AdvancedEditText editText) {
switch (action) {
case DEC_TAB:
Pair<Integer, Integer> selectionD =
Indentation.modifyIndent(editText.getTrueSelectionStart(), editText.getTrueSelectionEnd(), false, editText.getEditableText());
editText.setSelection(selectionD.first, selectionD.second);
break;
case INC_TAB:
Pair<Integer, Integer> selectionI =
Indentation.modifyIndent(editText.getTrueSelectionStart(), editText.getTrueSelectionEnd(), true, editText.getEditableText());
editText.setSelection(selectionI.first, selectionI.second);
break;
case SEARCH:
mSearch.showDialog();
break;
case SEARCHN:
mSearch.searchNext();
}
}
}
// list of shortcuts to display
private Shortcut[] mShortcuts = new Shortcut[]{
new ShortcutKey(KeyEvent.KEYCODE_DPAD_LEFT, "|"),
new ShortcutKey(KeyEvent.KEYCODE_DPAD_UP, "~"),
new ShortcutKey(KeyEvent.KEYCODE_DPAD_DOWN, "{"),
new ShortcutKey(KeyEvent.KEYCODE_DPAD_RIGHT, "}"),
new ShortcutAction(SA.DEC_TAB),
new ShortcutAction(SA.INC_TAB),
new ShortcutText("(", ")"),
new ShortcutText("[", "]"),
new ShortcutText("{", "}"),
new ShortcutText("var ", ""),
new ShortcutAction(SA.SEARCH),
new ShortcutAction(SA.SEARCHN),
};
private View.OnClickListener mShortcutButtonClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Button btn = (Button) v;
Shortcut shortcut = (Shortcut) btn.getTag();
shortcut.apply(mScriptText);
//mInputMethodManager.restartInput(mScriptText);
}
};
private void initializeShortcuts(ViewGroup view) {
Typeface typeface = LLApp.get().getIconsTypeface();
LayoutInflater inflater = getLayoutInflater();
for (Shortcut shortcut : mShortcuts) {
Button b = (Button) inflater.inflate(R.layout.sc_btn, null);
b.setTag(shortcut);
b.setText(shortcut.getLabel());
if(shortcut.isLabelIcon())
b.setTypeface(typeface);
b.setOnClickListener(mShortcutButtonClickListener);
view.addView(b);
}
}
}

View file

@ -376,7 +376,7 @@ public class BackupRestoreTool {
try {
ZipEntry ze=new ZipEntry(to+"/"+name);
zos.putNextEntry(ze);
copy(is, zos);
FileUtils.copyStream(is, zos);
zos.closeEntry();
} finally {
try { is.close(); } catch(Exception e) {/*pass*/}
@ -512,7 +512,7 @@ public class BackupRestoreTool {
parent.mkdirs();
}
fos=new FileOutputStream(out);
copy(zis, fos);
FileUtils.copyStream(zis, fos);
} catch(IOException e) {
throw e;
} finally {
@ -547,7 +547,7 @@ public class BackupRestoreTool {
try {
File out = new File(FileUtils.LL_TMP_DIR, name.substring(l));
fos=new FileOutputStream(out);
copy(zis, fos);
FileUtils.copyStream(zis, fos);
} finally {
if(fos!=null) try { fos.close(); } catch(Exception e) {}
}
@ -603,7 +603,7 @@ public class BackupRestoreTool {
parent.mkdirs();
}
fos=new FileOutputStream(out);
copy(zis, fos);
FileUtils.copyStream(zis, fos);
} finally {
if(fos!=null) try { fos.close(); } catch(Exception e) {}
}
@ -612,14 +612,6 @@ public class BackupRestoreTool {
return ze;
}
private static byte[] copy_buffer=new byte[4096];
private static void copy(InputStream from, OutputStream to) throws IOException {
int n;
while((n=from.read(copy_buffer))!=-1) {
to.write(copy_buffer, 0, n);
}
}
private static ZipEntry skipZipEntries(ZipInputStream zis, String prefix) throws IOException {
ZipEntry ze;
for(;;) {

View file

@ -543,7 +543,7 @@ public class UndoStack {
try {
int zorder = page.items.indexOf(new_item);
page.removeItem(new_item, false);
page.removeItem(new_item, true);
exchangeFilesWithUndo(icons, true, false); // restore old files from temp
Item old_item = Item.loadItemFromJSONObject(page, mOldJsonItem);
@ -566,7 +566,7 @@ public class UndoStack {
try {
int zorder = page.items.indexOf(old_item);
page.removeItem(old_item, false);
page.removeItem(old_item, true);
exchangeFilesWithUndo(icons, false, false); // restore new files from temp
Item new_item = Item.loadItemFromJSONObject(page, mNewJsonItem);

View file

@ -374,7 +374,9 @@ public class BindingEditDialog extends AlertDialog implements DialogInterface.On
} else {
name = mUserVariables.get(childPosition).name;
}
mFormulaEditText.getText().replace(mFormulaEditText.getSelectionStart(), mFormulaEditText.getSelectionEnd(), "$"+name);
int selstart = mFormulaEditText.getSelectionStart();
int selend = mFormulaEditText.getSelectionEnd();
mFormulaEditText.getText().replace(Math.min(selstart,selend), Math.max(selstart, selend), "$"+name);
dismiss();
return true;
}

View file

@ -50,7 +50,7 @@ public class FileProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
String path = uri.getPath().substring(1);
if(!path.startsWith(FileUtils.LL_TMP_DIR.getAbsolutePath())) {
if(!path.startsWith(FileUtils.LL_TMP_DIR.getAbsolutePath()) && !path.startsWith(FileUtils.LL_EXT_DIR.getAbsolutePath())) {
throw new IllegalArgumentException();
}

View file

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

View file

@ -24,6 +24,7 @@ import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.LLAppExtreme;
import net.pierrox.lightning_launcher.LWPSettings;
import net.pierrox.lightning_launcher.activities.ResourcesWrapperHelper;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.EventAction;
import net.pierrox.lightning_launcher.data.Page;
@ -288,8 +289,8 @@ public class LightningLWPService extends WallpaperService {
}
@Override
public Identity getIdentity() {
return Identity.LIVE_WALLPAPER;
public ScreenIdentity getIdentity() {
return ScreenIdentity.LIVE_WALLPAPER;
}
@Override
@ -298,17 +299,17 @@ public class LightningLWPService extends WallpaperService {
}
@Override
public void goToDesktopPosition(int page, float x, float y, float s, boolean animate) {
public void goToDesktopPosition(int page, float x, float y, float s, boolean animate, boolean absolute) {
if(Page.isDashboard(page) && page != getCurrentRootPage().id) {
LightningEngine engine = mMainPage.getEngine();
engine.getGlobalConfig().lwpScreen = page;
engine.notifyGlobalConfigChanged();
ItemLayout il = loadRootItemLayout(page, false, true, animate);
goToItemLayoutPosition(il, x, y, s, animate);
goToItemLayoutPosition(il, x, y, s, animate, absolute);
} else {
ItemLayout[] itemLayouts = getItemLayoutsForPage(page);
for (ItemLayout il : itemLayouts) {
goToItemLayoutPosition(il, x, y, s, animate);
goToItemLayoutPosition(il, x, y, s, animate, absolute);
}
}
}

View file

@ -162,11 +162,12 @@ public class MPReceiver extends BroadcastReceiver {
Bitmap icon=Utils.decodeScaledBitmapResource(rsrc, ri.getIconResource(), s.getStdIconSize());
Utils.saveIconToFile(default_icon_file, icon);
// do not update items on other pages, since they may have custom labels (two labels is not supported yet)
// do not update items on other pages, since they may have custom labels (two labels is not supported yet) and
// app shortcuts may have extras that would be lost if reseting the intent
if(p == Page.APP_DRAWER_PAGE) {
s.setLabel(label);
}
s.setIntent(intent);
}
s.mLastUpdateTime = now;
s.notifyChanged();

View file

@ -16,6 +16,7 @@ import net.pierrox.lightning_launcher.Version;
import net.pierrox.lightning_launcher.activities.Customize;
import net.pierrox.lightning_launcher.activities.Dashboard;
import net.pierrox.lightning_launcher.activities.RootSettings;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.data.ContainerPath;
import net.pierrox.lightning_launcher.data.LightningIntent;
import net.pierrox.lightning_launcher.data.Page;
@ -26,12 +27,12 @@ import net.pierrox.lightning_launcher.views.ItemLayout;
import net.pierrox.lightning_launcher_extreme.R;
public class PhoneUtils {
public static Intent createDesktopBookmarkShortcut(Context context, ItemLayout il, Page page, String label, Bitmap icon) {
public static Intent createDesktopBookmarkShortcut(Context context, ItemLayout il, Page page, String label, Bitmap icon, boolean animate) {
Matrix transform = null;
// arguments: either page is null (use il.getPage) or il is null (try to retrieve il from dashboard using page)
if(il == null) {
Screen screen = LLApp.get().getScreen(Screen.Identity.HOME);
Screen screen = LLApp.get().getScreen(ScreenIdentity.HOME);
if(screen != null) {
ItemLayout[] ils = screen.getItemLayoutsForPage(page.id);
if(ils.length > 0) {
@ -43,27 +44,30 @@ public class PhoneUtils {
transform = il.getLocalTransform();
}
Intent intent = new Intent(context, Dashboard.class);
float[] matrix_values = new float[9];
if(transform == null) {
transform = new Matrix();
}
transform.getValues(matrix_values);
intent.putExtra(LightningIntent.INTENT_EXTRA_PAGE, page.id);
float x = matrix_values[Matrix.MTRANS_X];
float y = matrix_values[Matrix.MTRANS_Y];
float s = matrix_values[Matrix.MSCALE_X];
boolean absolute;
if(il != null) {
RectF r = il.getVirtualEditBordersBounds();
if(r != null) {
x -= r.left;
y -= r.top;
}
x /= il.getWidth();
y /= il.getHeight();
absolute = false;
} else {
absolute = true;
}
intent.putExtra(LightningIntent.INTENT_EXTRA_TX, x);
intent.putExtra(LightningIntent.INTENT_EXTRA_TY, y);
intent.putExtra(LightningIntent.INTENT_EXTRA_TS, s);
Intent intent = getDesktopBookmarkIntent(context, page.id, x, y, s, animate, absolute);
Intent shortcut = new Intent();
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, label==null? context.getString(net.pierrox.lightning_launcher.R.string.shortcut_screen) : label);
@ -77,6 +81,19 @@ public class PhoneUtils {
return shortcut;
}
public static Intent getDesktopBookmarkIntent(Context context, int page, float x, float y, float scale, boolean animate, boolean absolute) {
Intent intent = new Intent(context, Dashboard.class);
intent.putExtra(LightningIntent.INTENT_EXTRA_DESKTOP, page);
intent.putExtra(LightningIntent.INTENT_EXTRA_X, x);
intent.putExtra(LightningIntent.INTENT_EXTRA_Y, y);
intent.putExtra(LightningIntent.INTENT_EXTRA_SCALE, scale);
intent.putExtra(LightningIntent.INTENT_EXTRA_ANIMATE, animate);
intent.putExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, absolute);
return intent;
}
public static void showPreferenceHelp(Context context, LLPreference preference) {
int id;
if(preference == null) {

View file

@ -1,108 +0,0 @@
package net.pierrox.lightning_launcher.util;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.faendir.rhino_android.RhinoAndroidHelper;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.plugin.IPluginService;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.script.ScriptExecutor;
import net.pierrox.lightning_launcher.script.ScriptManager;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import static net.pierrox.lightning_launcher.script.ScriptExecutor.PROPERTY_EVENT_SCREEN;
/**
* @author lukas
* @since 05.02.19
*/
public class PluginService extends Service {
private LightningEngine engine;
private final IPluginService service = new IPluginService.Stub() {
@Override
public int createScript(String code, String name, String path, int flags) {
ScriptManager scriptManager = engine.getScriptManager();
path = ScriptManager.sanitizeRelativePath(path);
if (scriptManager.getOrLoadScript(path, name) == null) {
Script script = scriptManager.createScriptForFile(name, path);
script.setSourceText(code);
script.flags = flags;
scriptManager.saveScript(script);
return script.id;
}
return Script.NO_ID;
}
@Override
public int createOrOverwriteScript(String code, String name, String path, int flags) {
ScriptManager scriptManager = engine.getScriptManager();
path = ScriptManager.sanitizeRelativePath(path);
Script script = scriptManager.getOrLoadScript(path, name);
if (script == null) {
script = scriptManager.createScriptForFile(name, path);
}
script.setSourceText(code);
script.flags = flags;
scriptManager.saveScript(script);
return script.id;
}
@Override
public void runScript(int id, String data) {
Screen screen = LLApp.get().getActiveScreen();
if (screen == null) {
LLApp.get().getScreen(Screen.Identity.BACKGROUND);
}
engine.getScriptExecutor().runScript(screen, id, "PLUGIN", data);
}
@Override
public String runCode(String code) {
Screen screen = LLApp.get().getActiveScreen();
if (screen == null) {
LLApp.get().getScreen(Screen.Identity.BACKGROUND);
}
ScriptExecutor executor = engine.getScriptExecutor();
if (executor.canRunScriptGlobally()) {
Scriptable scope = executor.prepareScriptScope();
org.mozilla.javascript.Context cx = RhinoAndroidHelper.prepareContext();
ScriptableObject.putProperty(scope, PROPERTY_EVENT_SCREEN, screen);
ScriptableObject.putProperty(scope, "ev_se", "DIRECT_PLUGIN");
ScriptableObject.putProperty(scope, "ev_d", null);
ScriptableObject.putProperty(scope, "ev_t", System.currentTimeMillis());
ScriptableObject.putProperty(scope, "ev_il", null);
ScriptableObject.putProperty(scope, "ev_iv", null);
try {
String script = "javascript:(function() {var _event = createEvent(ev_sc, ev_se, ev_d, ev_t, ev_il, ev_iv); var getEvent = function() { return _event;};\n" + code + "\n})();";
cx.setOptimizationLevel(-1);
org.mozilla.javascript.Script compiledScript = cx.compileString(script, null, 0, null);
if (compiledScript != null) {
return String.valueOf(compiledScript.exec(cx, scope));
}
} catch (RhinoException e) {
e.printStackTrace();
} finally {
// Exit from the context.
org.mozilla.javascript.Context.exit();
}
}
return null;
}
};
@Override
public void onCreate() {
engine = LLApp.get().getAppEngine();
}
@Override
public IBinder onBind(Intent intent) {
return service.asBinder();
}
}

View file

@ -0,0 +1,132 @@
package net.pierrox.lightning_launcher.util;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.api.Script;
import net.pierrox.lightning_launcher.api.ScriptException;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.plugin.IScriptService;
import net.pierrox.lightning_launcher.plugin.IScriptService_Stub;
import net.pierrox.lightning_launcher.script.ScriptExecutor;
import net.pierrox.lightning_launcher.script.ScriptManager;
import java.util.ArrayList;
import java.util.List;
/**
* @author lukas
* @since 05.02.19
*/
public class ScriptService extends Service implements IScriptService {
private LightningEngine mEngine;
@Override
public void onCreate() {
mEngine = LLApp.get().getAppEngine();
}
@Override
public IBinder onBind(Intent intent) {
return new IScriptService_Stub(this);
}
@Override
public int createScript(Script script) {
ScriptManager scriptManager = mEngine.getScriptManager();
script.setPath(ScriptManager.sanitizeRelativePath(script.getPath()));
if (findScript(scriptManager, script) != null) {
return Script.NO_ID;
}
net.pierrox.lightning_launcher.script.Script s = scriptManager.createScriptForFile(script.getName(), script.getPath());
s.setSourceText(script.getText());
s.flags = script.getFlags();
scriptManager.saveScript(s);
return s.id;
}
@Override
public int updateScript(Script script) {
ScriptManager scriptManager = mEngine.getScriptManager();
net.pierrox.lightning_launcher.script.Script s = findScript(scriptManager, script);
if (s == null) {
s = scriptManager.createScriptForFile(script.getName(), script.getPath());
}
s.setSourceText(script.getText());
s.name = script.getName();
s.setRelativePath(script.getPath());
s.flags = script.getFlags();
scriptManager.saveScript(s);
return s.id;
}
@Override
public void deleteScript(Script script) {
ScriptManager scriptManager = mEngine.getScriptManager();
net.pierrox.lightning_launcher.script.Script s = findScript(scriptManager, script);
if (s == null) {
throw new ScriptException("Script not found");
}
scriptManager.deleteScript(s);
}
@Override
public Script getScript(Script script) {
return map(findScript(mEngine.getScriptManager(), script));
}
@Override
public List<Script> getScriptsMatching(int flags) {
List<net.pierrox.lightning_launcher.script.Script> list = mEngine.getScriptManager().getAllScriptMatching(flags);
List<Script> result = new ArrayList<>();
for (net.pierrox.lightning_launcher.script.Script s : list) {
result.add(map(s));
}
return result;
}
@Override
public void runScript(Script script, String data, ScreenIdentity screenIdentity) throws ScriptException {
Screen screen = LLApp.get().getScreen(screenIdentity);
if (screen == null) {
throw new ScriptException("Screen not available");
}
net.pierrox.lightning_launcher.script.Script s = findScript(mEngine.getScriptManager(), script);
if (s == null) {
throw new ScriptException("Script with not found");
}
mEngine.getScriptExecutor().runScript(screen, s, "PLUGIN", data, null, null);
}
@Override
public String runCode(String code, ScreenIdentity screenIdentity) throws ScriptException {
Screen screen = LLApp.get().getScreen(screenIdentity);
if (screen == null) {
throw new ScriptException("Screen not available");
}
ScriptExecutor executor = mEngine.getScriptExecutor();
return String.valueOf(executor.runScriptAsFunction(screen, code, "", new Object[0], false, true));
}
private net.pierrox.lightning_launcher.script.Script findScript(ScriptManager scriptManager, Script script) {
script.setPath(ScriptManager.sanitizeRelativePath(script.getPath()));
net.pierrox.lightning_launcher.script.Script s;
if (script.getId() != Script.NO_ID) {
if (script.getId() < 0) {
//don't allow changing internal scripts
throw new ScriptException("Access to internal scripts not permitted");
}
s = scriptManager.getOrLoadScript(script.getId());
} else {
s = scriptManager.getOrLoadScript(script.getPath(), script.getName());
}
return s;
}
private Script map(net.pierrox.lightning_launcher.script.Script s) {
return s != null ? new Script(s.id, s.mSourceText, s.name, s.getRelativePath(), s.flags) : null;
}
}

View file

@ -0,0 +1,147 @@
package net.pierrox.lightning_launcher.util;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import net.pierrox.lightning_launcher_extreme.R;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import fr.xgouchet.texteditor.ui.AdvancedEditText;
/**
* Class that Manages a searchable dialog (currently for the script editor).
*/
public class Search {
private Activity mCntx;
private AdvancedEditText mEditText;
private AlertDialog mDialog;
private EditText mEdTxt;
private CheckBox mChkBackwards;
private CheckBox mChkCase;
private CheckBox mChkRegexp;
public Search(Activity cntx, AdvancedEditText editText) {
mCntx = cntx;
mEditText = editText;
// The dialog is saved and created on first use
mDialog = null;
}
/**
* Shows the dialog to search.
*/
public void showDialog(){
if(mDialog == null)
createDialog();
mDialog.show();
}
/**
* Performs a search as defined in the dialog.
* If the search fails the dialog is shown.
*/
public void searchNext() {
if(mDialog == null)
createDialog();
String searchText = mEdTxt.getText().toString();
if(searchText.isEmpty()) {
// no text to search
showDialog();
return;
}
String text = mEditText.getText().toString();
int flags = 0;
if(!mChkCase.isChecked()) flags |= Pattern.CASE_INSENSITIVE;
if(!mChkRegexp.isChecked()) flags |= Pattern.LITERAL;
Pattern pattern = Pattern.compile(searchText, flags);
int start = -1;
int end = -1;
Matcher matcher = pattern.matcher(text);
if(!mChkBackwards.isChecked()) {
// search fordwards
int from = mEditText.getTrueSelectionStart();
if (from != mEditText.getTrueSelectionEnd()) from++; // avoids returning the current selection
if( matcher.find(from) || matcher.find(0)){
// found one just after the selection or from the beginning
start = matcher.start();
end = matcher.end();
}
}else{
// search backwards
int until = mEditText.getTrueSelectionEnd();
while( matcher.find() && matcher.end() < until){
// found match before cursor, save
start = matcher.start();
end = matcher.end();
}
if(start == -1){
// not found, continue to find last one
while( matcher.find() ){
// found match, save
start = matcher.start();
end = matcher.end();
}
}
}
if( start != -1) {
// found, set selection
mEditText.setSelection(start, end);
}else{
// nothing found
showDialog();
}
}
/**
* Private: creates the dialog
*/
private void createDialog(){
View views = mCntx.getLayoutInflater().inflate(R.layout.dialog_search, null);
mEdTxt = views.findViewById(R.id.srch_text);
mChkBackwards = views.findViewById(R.id.srch_back);
mChkCase = views.findViewById(R.id.srch_case);
mChkRegexp = views.findViewById(R.id.srch_regexp);
mDialog = new AlertDialog.Builder(mCntx)
.setTitle(R.string.srch_ttl)
.setView(views)
.setCancelable(true)
.setPositiveButton(android.R.string.search_go, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// After this code a 'dialog.dismiss()' will be called, so the dialog won't be shown again if necessary.
// By posting a runnable for the next iteration, the code runs after the dismiss call and the dialog will be shown again if required.
// Other possible solutions require to override the button listener after the call to show (but the dialog won't 'fade out/in')
new Handler().post(new Runnable() {
@Override
public void run() {
searchNext();
}
});
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
}
}

View file

@ -237,6 +237,7 @@ public class Setup {
final PageConfig dashboard_config = dashboard.config;
dashboard_config.applyDefaultFolderConfig();
dashboard_config.defaultFolderConfig.outsideTapClose = true;
dashboard_config.screenOrientation = PageConfig.ScreenOrientation.PORTRAIT;
dashboard_config.gridPRowNum = 6;
dashboard_config.menuKey = new EventAction(GlobalConfig.USER_MENU, null);
@ -413,6 +414,7 @@ public class Setup {
Resources resources = LLApp.get().getResources();
final PageConfig config = drawer.config;
config.applyDefaultFolderConfig();
config.defaultFolderConfig.outsideTapClose = true;
config.gridPRowNum = config.gridLRowNum = 4;
config.scrollingDirection = PageConfig.ScrollingDirection.X;
if(Build.VERSION.SDK_INT>=19) {

View file

@ -61,7 +61,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
if(duplicate || found==null) {
int icon_size=(int)(home_page.config.defaultShortcutConfig.iconScale* Utils.getStandardIconSize());
Utils.ShortcutDescription sd=Utils.createShortcutFromIntent(context, data, icon_size);
if(sd != null) {
int id = home_page.findFreeItemId();
int[] cell = Utils.findFreeCell(home_page);
Shortcut shortcut = new Shortcut(home_page);
@ -77,6 +77,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
home_page.addItem(shortcut);
}
}
}
private void uninstallShortcut(Context context, Intent data) {
// TODO: implement uninstall shortcut

View file

@ -201,7 +201,7 @@ public class BoxEditorView extends View implements Runnable {
canvas.drawText(mBorder+" "+mBottom, w2, mBorderRect.bottom+dh, mTextPaint);
canvas.drawText(mPadding+" "+mBottom, w2, mPaddingRect.bottom+dh, mTextPaint);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
final float rx_r=mOuterRect.right-dh;
canvas.rotate(90, rx_r, h2);
canvas.drawText(mMargin+" "+mRight, rx_r, h2, mTextPaint);
@ -209,7 +209,7 @@ public class BoxEditorView extends View implements Runnable {
canvas.drawText(/*mPadding+" "+*/mRight, rx_r, h2+sh*2, mTextPaint);
canvas.restore();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
final float rx_l=mOuterRect.left+dh;
canvas.rotate(-90, rx_l, h2);
canvas.drawText(mMargin+" "+mLeft, rx_l, h2, mTextPaint);

View file

@ -2535,8 +2535,12 @@ public class CustomizeItemView extends MyViewPager implements LLPreferenceListVi
fcs.modifyFolderConfig().iconStyle = (FolderConfig.FolderIconStyle) enumValue;
if(object instanceof Folder) {
Folder folder = (Folder) object;
Page folder_page = folder.getOrLoadFolderPage();
ShortcutConfig.getIconBackFile(mPage.getIconDir(), folder.getId()).delete();
// when switching to a style with a dynamic background, force the recreation of
// the background with a default one, which will in turn trigger the recreation
// of a dynamic background
Utils.resetDynamicFolderBackground(ShortcutConfig.getIconBackFile(mPage.getIconDir(), folder.getId()), folder.getStdIconSize());
Utils.updateFolderIcon(folder);
} else {
Utils.updateFolderIconStyle((Page)object);

View file

@ -9,26 +9,32 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:padding="15dp">
android:layout_height="wrap_content">
<Button
android:id="@+id/backup"
android:layout_width="0dp"
android:layout_weight="0.5"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"/>
android:layout_height="wrap_content"/>
<Button
android:id="@+id/export"
android:layout_width="0dp"
android:layout_weight="0.5"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"/>
android:layout_height="match_parent"/>
</LinearLayout>
<Button
android:id="@+id/import_"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@android:drawable/divider_horizontal_bright"/>
<ListView
android:id="@+id/archives"
android:layout_height="match_parent"

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<EditText
android:id="@+id/srch_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="text" />
<CheckBox
android:id="@+id/srch_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/srch_back" />
<CheckBox
android:id="@+id/srch_case"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/srch_case" />
<CheckBox
android:id="@+id/srch_regexp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/srch_regexp" />
</LinearLayout>

View file

@ -13,18 +13,21 @@
android:id="@+id/sc_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_gravity="center_horizontal"
android:text="@string/sc_h"
android:textStyle="italic"
android:layout_gravity="center_horizontal" />
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="italic" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<fr.xgouchet.texteditor.ui.AdvancedEditText
android:id="@+id/sc_text"
style="@style/sc_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/sc_text" />
</LinearLayout>
android:layout_height="match_parent" />
<HorizontalScrollView
android:layout_width="wrap_content"
@ -33,10 +36,25 @@
<LinearLayout
android:id="@+id/completions"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
</FrameLayout>
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal">
<LinearLayout
android:id="@+id/shortcuts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
</LinearLayout>
<LinearLayout
android:id="@+id/left_pane"
@ -162,6 +180,13 @@
android:checked="true"
android:text="@string/sc_w"/>
<CheckBox
android:id="@+id/sc_ind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/sc_ind" />
<TextView
android:id="@+id/sc_a"
android:layout_width="wrap_content"

View file

@ -7,9 +7,10 @@ buildscript {
url 'https://maven.google.com/'
name 'Google'
}
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.3.2'
}
}

View file

@ -1,12 +1,11 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
compileSdkVersion 28
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
targetSdkVersion 28
versionCode 1
versionName "1.0"
buildConfigField "boolean", "IS_BETA", "true"
@ -38,4 +37,5 @@ dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile files('libs/dx.jar')
compile 'net.pierrox.android:lsvg:1.0'
compile project(':plugin-api')
}

View file

@ -3,5 +3,6 @@
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
</manifest>

View file

@ -24,10 +24,12 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout.LayoutParams;
@ -80,11 +82,9 @@ public class SystemBarTintManager {
* Constructor. Call this in the host activity onCreate method after its
* content view has been set. You should always create new instances when
* the host activity is recreated.
*
* @param activity The host activity.
*/
@TargetApi(19)
public SystemBarTintManager(Window window) {
public SystemBarTintManager(final Window window) {
Context context = window.getContext();
mStatusBarAnimEnter = AnimationUtils.loadAnimation(context, R.anim.sb_in);
mStatusBarAnimExit = AnimationUtils.loadAnimation(context, R.anim.sb_out);
@ -98,7 +98,7 @@ public class SystemBarTintManager {
setupNavBarLayoutParams();
}
public void onOrientationChanged(Window window) {
public void onConfigurationChanged(Window window) {
mConfig = new SystemBarConfig(window);
setupStatusBarLayoutParams();
@ -362,6 +362,13 @@ public class SystemBarTintManager {
// private final int mNavigationBarWidth;
private final boolean mIsNavigationAtBottom;
// These values are kept in order to be reused when the window insets are not available. This
// is the case when the view is not attached to the window. Also, display cutouts are never
// available in the context of the overlay desktop. Display cutouts are not supposed to change
// so it should be safe enough.
private static int sSafeInsetWidth = 0;
private static int sSafeInsetHeight = 0;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private SystemBarConfig(Window window) {
Resources res = window.getContext().getResources();
@ -383,11 +390,21 @@ public class SystemBarTintManager {
DisplayMetrics realDm = new DisplayMetrics();
window.getWindowManager().getDefaultDisplay().getRealMetrics(realDm);
if (Build.VERSION.SDK_INT >= 28) {
WindowInsets windowInsets = window.getDecorView().getRootWindowInsets();
if(windowInsets != null) {
DisplayCutout cutout = windowInsets.getDisplayCutout();
if(cutout != null) {
sSafeInsetWidth = cutout.getSafeInsetLeft() + cutout.getSafeInsetRight();
sSafeInsetHeight = cutout.getSafeInsetTop() + cutout.getSafeInsetBottom();
}
}
}
mIsNavigationAtBottom = realDm.widthPixels == dm.widthPixels;
if(mIsInPortrait || mIsNavigationAtBottom) {
mNavigationBarHeight = realDm.heightPixels - dm.heightPixels;// - statusBarHeight;
mNavigationBarHeight = realDm.heightPixels - dm.heightPixels - sSafeInsetHeight;
} else {
mNavigationBarHeight = realDm.widthPixels - dm.widthPixels;
mNavigationBarHeight = realDm.widthPixels - dm.widthPixels - sSafeInsetWidth;
}
mHasNavigationBar = (mNavigationBarHeight > 0);
}

View file

@ -12,8 +12,8 @@ import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.view.ViewGroup;
import net.pierrox.lightning_launcher.activities.ResourcesWrapperHelper;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.SystemConfig;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Item;
@ -26,7 +26,6 @@ import net.pierrox.lightning_launcher.script.api.Property;
import net.pierrox.lightning_launcher.views.MyAppWidgetHostView;
import net.pierrox.lightning_launcher.views.NativeImage;
import net.pierrox.lightning_launcher.views.SharedAsyncGraphicsDrawable;
import org.json.JSONObject;
import java.io.File;
@ -248,7 +247,7 @@ public abstract class LLApp extends Application {
public void onScreenCreated(Screen screen) {
int index;
if(screen.getIdentity() == Screen.Identity.LIVE_WALLPAPER) {
if(screen.getIdentity() == ScreenIdentity.LIVE_WALLPAPER) {
// never put the live wallpaper at the top of the stack, always the bottom
index = 0;
} else {
@ -263,7 +262,7 @@ public abstract class LLApp extends Application {
public void onScreenResumed(Screen screen) {
// never bring the LWP to the top of the stack
if(screen.getIdentity() != Screen.Identity.LIVE_WALLPAPER && mScreens.size() > 1) {
if(screen.getIdentity() != ScreenIdentity.LIVE_WALLPAPER && mScreens.size() > 1) {
mScreens.remove(screen);
mScreens.add(screen);
}
@ -271,7 +270,7 @@ public abstract class LLApp extends Application {
public void onScreenPaused(Screen screen) {
// the LWP is always at the bottom of the stack
if(screen.getIdentity() != Screen.Identity.LIVE_WALLPAPER) {
if(screen.getIdentity() != ScreenIdentity.LIVE_WALLPAPER) {
int size = mScreens.size();
if (size > 2) {
mScreens.remove(screen);
@ -280,7 +279,7 @@ public abstract class LLApp extends Application {
}
}
public Screen getScreen(Screen.Identity identity) {
public Screen getScreen(ScreenIdentity identity) {
for (Screen screen : mScreens) {
if(screen.getIdentity() == identity) {
return screen;
@ -420,8 +419,8 @@ public abstract class LLApp extends Application {
}
@Override
public Identity getIdentity() {
return Identity.BACKGROUND;
public ScreenIdentity getIdentity() {
return ScreenIdentity.BACKGROUND;
}
@Override

View file

@ -6,13 +6,14 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.R;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.EventAction;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.R;
public class MultiPurposeTransparentActivity extends ResourceWrapperActivity {
private final static String INTENT_EXTRA_TYPE = "t";
@ -69,7 +70,9 @@ public class MultiPurposeTransparentActivity extends ResourceWrapperActivity {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// should pass the base dir of the engine in the intent and use it instead of the default engine
LLApp.get().getAppEngine().getScriptManager().getOrLoadScript(script_id).setFlag(Script.FLAG_DISABLED, true);
LLApp llApp = LLApp.get();
llApp.getAppEngine().getScriptManager().getOrLoadScript(script_id).setFlag(Script.FLAG_DISABLED, true);
Toast.makeText(llApp, R.string.sc_disable_toast, Toast.LENGTH_LONG).show();
finish();
}
});
@ -81,7 +84,7 @@ public class MultiPurposeTransparentActivity extends ResourceWrapperActivity {
case TYPE_RUN_ACTION:
int action = intent.getIntExtra(INTENT_EXTRA_ACTION, GlobalConfig.NOTHING);
String data = intent.getStringExtra(INTENT_EXTRA_DATA);
app.getScreen(Screen.Identity.BACKGROUND).runAction(app.getAppEngine(), "BACKGROUND", new EventAction(action, data));
app.getScreen(ScreenIdentity.BACKGROUND).runAction(app.getAppEngine(), "BACKGROUND", new EventAction(action, data));
finish();
break;
}

View file

@ -23,7 +23,9 @@ public class FolderConfig extends JsonLoader {
public enum FolderIconStyle {
NORMAL,
GRID_2_2,
STACK
STACK,
GRID_AUTO,
GRID_3_3
}
// public enum FolderBorderStyle {
@ -47,6 +49,7 @@ public class FolderConfig extends JsonLoader {
public FolderAnimation animationIn=FolderAnimation.OPEN_CLOSE;
public FolderAnimation animationOut=FolderAnimation.OPEN_CLOSE;
public FolderIconStyle iconStyle=FolderIconStyle.GRID_2_2;
public boolean outsideTapClose=false;
public boolean autoClose=false;
public boolean closeOther=false;
public boolean animationGlitchFix=false;

View file

@ -95,6 +95,8 @@ public class PageConfig extends JsonLoader {
public boolean navigationBarOverlap =false;
public int statusBarColor=0;
public int navigationBarColor=0;
public boolean statusBarLight=false;
public boolean navigationBarLight=false;
public ScreenOrientation screenOrientation=ScreenOrientation.SYSTEM;
// public ScreenRotationWhat screenRotationWhat=ScreenRotationWhat.ROTATE_WORKSPACE;

View file

@ -11,6 +11,7 @@ import net.pierrox.lightning_launcher.engine.variable.Variable;
import net.pierrox.lightning_launcher.script.Script;
import java.net.URISyntaxException;
import java.text.DecimalFormat;
public class EventAction {
public int action;
@ -84,9 +85,19 @@ public class EventAction {
case GlobalConfig.GO_DESKTOP_POSITION:
try {
Intent intent = Intent.parseUri(data, 0);
int p = intent.getIntExtra(LightningIntent.INTENT_EXTRA_PAGE, Page.FIRST_DASHBOARD_PAGE);
int p = intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, Page.FIRST_DASHBOARD_PAGE);
Page page = engine.getOrLoadPage(p);
return Utils.formatPageName(page, page.findFirstOpener());
String description = Utils.formatPageName(page, page.findFirstOpener());
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
float x = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_X, 0);
float y = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0);
float s = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_SCALE, 1);
boolean absolute = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, true);
DecimalFormat df = new DecimalFormat("0.##");
description += absolute ? " @" : " +";
description += df.format(x)+"x"+df.format(y)+"/"+df.format(s);
}
return description;
} catch (URISyntaxException e) {
// pass
}

View file

@ -16,6 +16,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileUtils {
public static final String WALLPAPER_DIR = "wp";
@ -45,6 +46,15 @@ public class FileUtils {
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");
private static byte[] copy_buffer=new byte[4096];
public static void copyStream(InputStream from, OutputStream to) throws IOException {
int n;
while((n=from.read(copy_buffer))!=-1) {
to.write(copy_buffer, 0, n);
}
}
public static void saveStringToFile(String what, File out) throws IOException {
FileOutputStream fos=null;
try {

View file

@ -5,9 +5,11 @@ public class LightningIntent {
public static final String INTENT_EXTRA_DATA = "d";
public static final String INTENT_EXTRA_EVENT_ACTION = "ea";
public static final String INTENT_EXTRA_TARGET = "t";
public static final String INTENT_EXTRA_PAGE = "p";
public static final String INTENT_EXTRA_TX = "x";
public static final String INTENT_EXTRA_TY = "y";
public static final String INTENT_EXTRA_TS = "s";
public static final String INTENT_EXTRA_DESKTOP = "p";
public static final String INTENT_EXTRA_X = "x";
public static final String INTENT_EXTRA_Y = "y";
public static final String INTENT_EXTRA_SCALE = "s";
public static final String INTENT_EXTRA_LOAD_SCRIPT_FROM_PACKAGE = "b";
public static final String INTENT_EXTRA_ANIMATE = "n";
public static final String INTENT_EXTRA_ABSOLUTE = "l";
}

View file

@ -35,8 +35,8 @@ public class PageIndicator extends Item implements ShortcutConfigStylable {
public int dotsMarginX = 10;
public int dotsMarginY = 10;
public int dotsOuterRadius = 8;
public int dotsInnerRadius = 6;
public int dotsOuterStrokeWidth = 0;
public int dotsInnerRadius = 5;
public int dotsOuterStrokeWidth = 2;
public int dotsOuterColor = Color.WHITE;
public int dotsInnerColor = Color.WHITE;
public String rawFormat = "%1$+5.0f %2$+5.0f | %3$6.3f";

View file

@ -400,9 +400,9 @@ public class PageProcessor {
cn = intent.getComponent();
if(cn.getPackageName().equals(pkg_name_to)) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_PAGE) && translated_page_ids != null) {
int old_bookmark_page = intent.getIntExtra(LightningIntent.INTENT_EXTRA_PAGE, Page.NONE);
intent.putExtra(LightningIntent.INTENT_EXTRA_PAGE, translated_page_ids.get(old_bookmark_page));
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP) && translated_page_ids != null) {
int old_bookmark_page = intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, Page.NONE);
intent.putExtra(LightningIntent.INTENT_EXTRA_DESKTOP, translated_page_ids.get(old_bookmark_page));
modified = true;
} else {
EventAction ea = Utils.decodeEventActionFromLightningIntent(intent);
@ -417,14 +417,17 @@ public class PageProcessor {
}
if(do_scale) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_TX)) {
intent.putExtra(LightningIntent.INTENT_EXTRA_TX, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_TX, 0) * sx);
intent.putExtra(LightningIntent.INTENT_EXTRA_TY, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_TY, 0) * sy);
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
boolean absolute = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, true);
if(absolute) {
intent.putExtra(LightningIntent.INTENT_EXTRA_X, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_X, 0) * sx);
intent.putExtra(LightningIntent.INTENT_EXTRA_Y, intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0) * sy);
modified = true;
}
}
}
}
}
return modified;
}

View file

@ -540,7 +540,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
// alays filter the reflection (minor overhead compared with other processing involved)
paint.setFilterBitmap(true);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
canvas.translate(0, boxLayer.bottom+boxLayer.bottom*c.iconReflectionScale-boxImage.height()*c.iconReflectionOverlap);
canvas.scale(1, -c.iconReflectionScale);
Paint mirror_icon_paint=new Paint();
@ -553,7 +553,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
back.draw(canvas);
}
canvas.saveLayer(0, 0, finalWidth, finalHeight, null, Canvas.ALL_SAVE_FLAG);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
canvas.drawBitmap(baseIcon, null, boxImage, paint);
canvas.restore();
if(mask!=null) {
@ -568,7 +568,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
canvas.restore(); // matrix
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
canvas.translate(0, boxLayer.bottom-boxLayer.height()*c.iconReflectionOverlap+1);
canvas.drawRect(0, 0, boxLayer.width(), reflection_height, mirror_icon_paint);
canvas.restore();
@ -581,7 +581,7 @@ public class Shortcut extends Item implements ShortcutConfigStylable, SharedAsyn
back.draw(canvas);
}
canvas.saveLayer(0, 0, finalWidth, finalHeight, null, Canvas.ALL_SAVE_FLAG);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
canvas.drawBitmap(baseIcon, null, boxImage, paint);
canvas.restore();
if(mask!=null) {

View file

@ -1,5 +1,6 @@
package net.pierrox.lightning_launcher.data;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
@ -11,9 +12,11 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@ -1032,6 +1035,10 @@ public class Utils {
public static ShortcutDescription createShortcutFromIntent(Context context, Intent data, int max_icon_size) {
// this comes from Launcher2
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
if(intent == null) {
return null;
}
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
@ -1062,6 +1069,37 @@ public class Utils {
return sd;
}
@TargetApi(Build.VERSION_CODES.O)
public static ShortcutDescription createPinItemRequestFromIntent(Context context, Intent intent) {
Parcelable extra = intent.getParcelableExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST);
if(extra instanceof LauncherApps.PinItemRequest) {
LauncherApps.PinItemRequest request = (LauncherApps.PinItemRequest) extra;
if (request.getRequestType() == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT) {
final LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
ShortcutInfo shortcutInfo = request.getShortcutInfo();
final Drawable iconDrawable = launcherApps.getShortcutIconDrawable(shortcutInfo, Utils.getLauncherIconDensity());
Bitmap icon = Utils.createBitmapFromDrawable(iconDrawable);
Intent si = new Intent(Shortcut.INTENT_ACTION_APP_SHORTCUT);
si.putExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_ID, shortcutInfo.getId());
si.putExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_PKG, shortcutInfo.getPackage());
si.putExtra(Shortcut.INTENT_EXTRA_APP_SHORTCUT_DISABLED_MSG, shortcutInfo.getDisabledMessage());
ShortcutDescription sd=new ShortcutDescription();
sd.name = shortcutInfo.getShortLabel().toString();
sd.icon = icon;
sd.intent = si;
request.accept();
return sd;
}
}
return null;
}
public static void deleteDirectory(File dir, boolean delete_root) {
File[] files=dir.listFiles();
if(files!=null) {
@ -1101,6 +1139,59 @@ public class Utils {
}
}
private static final float DYNAMIC_FOLDER_BG_MARGIN=0.03125f;
private static void buildDynamicFolderBackground(Canvas canvas, int icon_width, int icon_height) {
canvas.drawARGB(0, 0, 0, 0);
Paint bg_paint=new Paint(Paint.ANTI_ALIAS_FLAG);
bg_paint.setShader(new RadialGradient(icon_width/2, icon_height/2, (float) Math.sqrt(icon_width*icon_width+icon_height*icon_height), 0xff59514c, 0xff272424, TileMode.CLAMP));
canvas.drawRoundRect(new RectF(0, 0, icon_width, icon_height), DYNAMIC_FOLDER_BG_MARGIN*2*icon_width, DYNAMIC_FOLDER_BG_MARGIN*2*icon_height, bg_paint);
}
public static void resetDynamicFolderBackground(File image_file, int size) {
Bitmap icon = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas=new Canvas(icon);
buildDynamicFolderBackground(canvas, size, size);
Utils.saveIconToFile(image_file, icon);
}
private static boolean hasDynamicFolderBackground(File image_file) {
// return true if the current folder background is a dynamic one (the one with a gray
// rounded rectangle, built with the function above)
// Historically there has been no metadata to distinguish between the dynamic folder bg and
// a manually chosen one. This function naively compares the current bitmap with a reference
// dynamically computed bitmap. This is kind of crappy but I can't see a better way to make
// it work with existing setups.
if(!image_file.exists()) {
return false;
}
// load the current bitmap (with a max size to limite computations to a reasonable amount)
Bitmap current = loadBitmap(image_file, 0, 32, 32);
// create a reference background with the same size
int w = current.getWidth();
int h = current.getHeight();
Bitmap reference = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas=new Canvas(reference);
buildDynamicFolderBackground(canvas, w, h);
// now compare pixels (only the blue channel, this is probably enough)
int diff = 0; // enough for 2^15 pixels
for(int x=0; x<w; x++) {
for(int y=0; y<h; y++) {
int d = (current.getPixel(x, y)&0xff) - (reference.getPixel(x, y)&0xff);
diff += d*d;
}
}
int s = diff / (w*h);
return s < 4;
}
public static void updateFolderIcon(Folder folder) {
Page folder_page = folder.getOrLoadFolderPage();
FolderConfig fc = folder.getFolderConfig();
@ -1112,6 +1203,8 @@ public class Utils {
File icon_effect_background;
icon_effect_background = ShortcutConfig.getIconBackFile(folder_container_icon_dir, folder.mId);
boolean hasDynamicFolderBackground = hasDynamicFolderBackground(icon_effect_background);
Bitmap icon;
if(style==FolderIconStyle.NORMAL) {
icon=null; // do not update the icon, keep the current one
@ -1162,35 +1255,62 @@ public class Utils {
icon=Bitmap.createBitmap(icon_width, icon_height, Bitmap.Config.ARGB_8888);
Canvas canvas=new Canvas(icon);
final float margin=0.03125f;
canvas.drawARGB(0, 0, 0, 0);
Paint bg_paint=new Paint(Paint.ANTI_ALIAS_FLAG);
bg_paint.setShader(new RadialGradient(icon_width/2, icon_height/2, (float) Math.sqrt(icon_width*icon_width+icon_height*icon_height), 0xff59514c, 0xff272424, TileMode.CLAMP));
canvas.drawRoundRect(new RectF(0, 0, icon_width, icon_height), margin*2*icon_width, margin*2*icon_height, bg_paint);
if(hasDynamicFolderBackground) {
buildDynamicFolderBackground(canvas, icon_width, icon_height);
}
Paint bitmap_paint=new Paint(Paint.FILTER_BITMAP_FLAG|Paint.ANTI_ALIAS_FLAG);
if(style==FolderIconStyle.GRID_2_2) {
final int w=2;
final int h=2;
if(style==FolderIconStyle.GRID_2_2 || style==FolderIconStyle.GRID_3_3 || style==FolderIconStyle.GRID_AUTO) {
int l=folder_items.size();
final int w;
final int h;
switch(style) {
case GRID_2_2:
w = 2;
h = 2;
break;
case GRID_3_3:
w = 3;
h = 3;
break;
case GRID_AUTO:
default:
if(l <= 4) {
w = 2;
h = 2;
} else {
w = 3;
h = 3;
}
break;
}
final float bw=icon_width/(float)w;
final float bh=icon_height/(float)h;
final float mw=margin*icon_width;
final float mh=margin*icon_height;
final float mw=DYNAMIC_FOLDER_BG_MARGIN*icon_width;
final float mh=DYNAMIC_FOLDER_BG_MARGIN*icon_height;
final int max=w*h;
if(hasDynamicFolderBackground) {
Paint line_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
line_paint.setColor(0xff8C7F77);
canvas.drawLine(icon_width/2+0.5f, mh, icon_width/2+0.5f, icon_height-mh, line_paint);
canvas.drawLine(mw, icon_height/2+0.5f, icon_width-mh, icon_height/2+0.5f, line_paint);
for (int x = 1; x < w; x++) {
float p = x * icon_width / w + 0.5f;
canvas.drawLine(p, mh, p, icon_height - mh, line_paint);
}
for (int y = 1; y < h; y++) {
float p = y * icon_height / h + 0.5f;
canvas.drawLine(mw, p, icon_width - mh, p, line_paint);
}
storeFolderIconBackground(icon_effect_background, folder_container_icon_dir, folder, icon);
}
icon.eraseColor(0);
int l=folder_items.size();
int x=0;
int y=0;
int n=0;
@ -1221,11 +1341,15 @@ public class Utils {
} else {
if(hasDynamicFolderBackground) {
storeFolderIconBackground(icon_effect_background, folder_container_icon_dir, folder, icon);
}
icon.eraseColor(0);
final int max=4;
final float mw=margin*icon_width;
final float mh=margin*icon_height;
final float mw=DYNAMIC_FOLDER_BG_MARGIN*icon_width;
final float mh=DYNAMIC_FOLDER_BG_MARGIN*icon_height;
RectF dst=new RectF();
int n=folder_items.size();
@ -1269,12 +1393,9 @@ public class Utils {
}
private static void storeFolderIconBackground(File icon_effect_background, File folder_container_icon_dir, Folder folder, Bitmap icon) {
if(!icon_effect_background.exists()) {
Utils.saveIconToFile(icon_effect_background, icon);
ShortcutConfig new_sc = folder.modifyShortcutConfig();
new_sc.loadAssociatedIcons(folder_container_icon_dir, folder.mId);
}
icon.eraseColor(0);
}
public static void updateContainerIconIfNeeded(Page page) {
@ -1479,7 +1600,17 @@ public class Utils {
public static Item addAndroidShortcutFromIntent(Context context, Intent data, Page page, int x, int y, float scale) {
int icon_size=(int)(page.config.defaultShortcutConfig.iconScale*getStandardIconSize());
ShortcutDescription sd=createShortcutFromIntent(context, data, icon_size);
if(sd == null) {
sd = createPinItemRequestFromIntent(context, data);
}
if(sd == null) {
sd = new ShortcutDescription();
sd.name = "no shortcut";
sd.intent = new Intent();
}
return addShortcut(sd.name, sd.icon, sd.intent, page, x, y, scale, true);
}

View file

@ -652,7 +652,7 @@ public class LightningEngine implements Page.PageListener {
if (item.getClass() == Shortcut.class) {
Shortcut shortcut = (Shortcut) item;
Intent intent = shortcut.getIntent();
if (Shortcut.INTENT_ACTION_APP_SHORTCUT.equals(intent.getAction())) {
if (intent != null && Shortcut.INTENT_ACTION_APP_SHORTCUT.equals(intent.getAction())) {
return intent;
}
}

View file

@ -31,6 +31,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;
@ -39,6 +40,7 @@ import com.readystatesoftware.systembartint.SystemBarTintManager;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.R;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.FolderConfig;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.configuration.ItemConfig;
@ -82,7 +84,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.ItemViewListener, Page.PageListener {
public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.ItemViewListener, Page.PageListener, FolderView.OnTapOutsideListener {
public static final int PAGE_DIRECTION_HINT_BACKWARD = -1;
public static final int PAGE_DIRECTION_HINT_FORWARD = 1;
@ -90,17 +92,6 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
public static final int PAGE_DIRECTION_HINT_DONT_MOVE = 2;
public static final int PAGE_DIRECTION_HINT_NO_ANIMATION = 3;
public enum Identity {
BACKGROUND,
HOME,
APP_DRAWER,
LOCK,
FLOATING,
CUSTOMIZE,
DESKTOP_PREVIEW,
LIVE_WALLPAPER
}
private static final String SIS_TARGET_ITEM_LAYOUT="sa";
private static final String SIS_LAST_TOUCHED_X="sb";
private static final String SIS_LAST_TOUCHED_Y="sc";
@ -110,7 +101,7 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
protected Context mContext;
private Window mWindow;
private boolean mHasWindowFocus;
private SystemBarTintManager mSystemBarTintManager;
protected SystemBarTintManager mSystemBarTintManager;
private ViewGroup mContentView;
private View mDesktopView;
@ -198,6 +189,24 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
}
}
};
mContentView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
// select API 28 because this is linked with the display cutout stuff
if (Build.VERSION.SDK_INT >= 28) {
WindowInsets insets = mContentView.getRootWindowInsets();
if (insets != null) {
mSystemBarTintManager.onConfigurationChanged(mWindow);
onSystemBarsSizeChanged();
}
}
}
@Override
public void onViewDetachedFromWindow(View view) {
}
});
}
}
@ -298,7 +307,7 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
return !mIsResumed;
}
public abstract Identity getIdentity();
public abstract ScreenIdentity getIdentity();
public Context getContext() {
return mContext;
@ -828,6 +837,7 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
return runAction(engine, "C_LONG_CLICK", ea.action==GlobalConfig.UNSET ? engine.getGlobalConfig().bgLongTap : ea);
}
});
fv.setOnTapOutsideListener(this);
mFolderContainer.addView(fv);
mFolderViews.add(fv);
}
@ -1012,6 +1022,11 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
}
}
@Override
public void onTapOutside(FolderView fv) {
closeFolder(fv, true);
}
/***************************************** GEOMETRY ***********************************/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@ -1128,40 +1143,47 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
public void executeGoToDesktopPositionIntent(Intent intent) {
int page = intent.getIntExtra(LightningIntent.INTENT_EXTRA_PAGE, Page.FIRST_DASHBOARD_PAGE);
int page = intent.getIntExtra(LightningIntent.INTENT_EXTRA_DESKTOP, Page.FIRST_DASHBOARD_PAGE);
if(Page.isDashboard(page) && page != getCurrentRootPage().id) {
loadRootItemLayout(page, false, true, true);
}
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_TX)) {
float x = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_TX, 0);
float y = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_TY, 0);
float s = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_TS, 1);
goToDesktopPosition(page, x, y, s, true);
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_X)) {
float x = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_X, 0);
float y = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_Y, 0);
float s = intent.getFloatExtra(LightningIntent.INTENT_EXTRA_SCALE, 1);
boolean absolute = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ABSOLUTE, true);
boolean animate = intent.getBooleanExtra(LightningIntent.INTENT_EXTRA_ANIMATE, true);
goToDesktopPosition(page, x, y, s, animate, absolute);
}
}
public void goToDesktopPosition(int page, float x, float y, float s, boolean animate) {
public void goToDesktopPosition(int page, float x, float y, float s, boolean animate, boolean absolute) {
if(Page.isDashboard(page) && page != getCurrentRootPage().id) {
ItemLayout il = loadRootItemLayout(page, false, true, animate);
goToItemLayoutPosition(il, x, y, s, animate);
goToItemLayoutPosition(il, x, y, s, animate, absolute);
} else {
ItemLayout[] itemLayouts = getItemLayoutsForPage(page);
for (ItemLayout il : itemLayouts) {
goToItemLayoutPosition(il, x, y, s, animate);
goToItemLayoutPosition(il, x, y, s, animate, absolute);
}
}
}
public void goToItemLayoutPosition(ItemLayout il, float x, float y, float s, boolean animate) {
public void goToItemLayoutPosition(ItemLayout il, float x, float y, float s, boolean animate, boolean absolute) {
Page page = il.getPage();
if(page.isDashboard() && page != getCurrentRootPage()) {
loadRootItemLayout(page.id, false, true, true);
}
if(absolute) {
if (animate) {
il.animateZoomTo(x, y, s);
} else {
il.moveTo(x, y, s);
}
} else {
il.goToPage(x, y, s, animate);
}
}
public void zoomInOrOut(ItemLayout il) {
@ -1469,6 +1491,10 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
}
}
public void onSystemBarsSizeChanged() {
// pass, override in subclasses when needed
}
public void configureSystemBarsColor(PageConfig c) {
if(Build.VERSION.SDK_INT>=19) {
mSystemBarTintManager.setStatusBarTintEnabled(!c.statusBarHide || mForceDisplayStatusBar);
@ -1483,6 +1509,24 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
flags &= ~(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
mWindow.setFlags(flags, 0xffffffff);
if (Build.VERSION.SDK_INT >= 23) {
int f = mContentView.getSystemUiVisibility();
if(c.statusBarLight) {
f |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
f &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
mContentView.setSystemUiVisibility(f);
}
if (Build.VERSION.SDK_INT >= 26) {
int f = mContentView.getSystemUiVisibility();
if(c.navigationBarLight) {
f |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
} else {
f &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
}
mContentView.setSystemUiVisibility(f);
}
try {
Method setStatusBarColor = mWindow.getClass().getMethod("setStatusBarColor", int.class);
setStatusBarColor.invoke(mWindow, 0);
@ -1492,7 +1536,6 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
e.printStackTrace();
}
} else {
flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
mWindow.setFlags(flags, 0xffffffff);
}
@ -1639,7 +1682,7 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
if(eventAction != null) {
runAction(engine, "SHORTCUT", eventAction, itemView.getParentItemLayout(), itemView);
} else {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_PAGE)) {
if(intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP)) {
executeGoToDesktopPositionIntent(intent);
}
}
@ -1777,7 +1820,7 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
if (eventAction != null) {
runAction(engine, source, eventAction, il, itemView);
} else {
if (intent.hasExtra(LightningIntent.INTENT_EXTRA_PAGE)) {
if (intent.hasExtra(LightningIntent.INTENT_EXTRA_DESKTOP)) {
executeGoToDesktopPositionIntent(intent);
}
}
@ -2028,7 +2071,7 @@ public abstract class Screen implements ItemLayout.ItemLayoutListener, ItemView.
/***************************************** SCREEN ORIENTATION ***********************************/
public void onOrientationChanged() {
if(mSystemBarTintManager != null) {
mSystemBarTintManager.onOrientationChanged(mWindow);
mSystemBarTintManager.onConfigurationChanged(mWindow);
}
updateOrientationOrRotation();

View file

@ -2,6 +2,10 @@ package net.pierrox.lightning_launcher.overlay;
import android.animation.Animator;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@ -13,6 +17,7 @@ import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.KeyEvent;
@ -30,9 +35,12 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import com.readystatesoftware.systembartint.SystemBarTintManager;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.R;
import net.pierrox.lightning_launcher.activities.ResourcesWrapperHelper;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.EventAction;
import net.pierrox.lightning_launcher.data.Page;
@ -52,6 +60,9 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
private static final int OPEN_CLOSE_ANIMATION_DURATION = 300;
private static final String NOTIFICATION_CHANNEL_ID = "LL_SERVICES";
private static final int NOTIFICATION_ID = 0;
private WindowScreen mScreen;
private ResourcesWrapperHelper mResourcesWrapperHelper;
@ -176,6 +187,8 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
// |WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
// |WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE
|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|0,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.LEFT | Gravity.TOP;
@ -326,12 +339,43 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
configureScreen();
configureDrawer();
if (Build.VERSION.SDK_INT >= 26) {
CharSequence name = "Lightning Services";
String description = "Background Launcher activities";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
Intent notificationIntent = LLApp.get().getWindowServiceIntent();
notificationIntent.setAction(WindowService.INTENT_ACTION_SHOW);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
Notification.Builder builder;
if (Build.VERSION.SDK_INT >= 26) {
builder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID);
} else {
builder = new Notification.Builder(this);
}
builder.setContentTitle(getString(R.string.ov_r))
.setContentIntent(pendingIntent)
.setCategory(Notification.CATEGORY_SERVICE)
.setPriority(Notification.PRIORITY_LOW);
Notification notification = builder.build();
startForeground(NOTIFICATION_ID, notification);
}
@Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
final LLApp app = LLApp.get();
app.getAppEngine().unregisterGlobalConfigChangeListener(this);
@ -778,18 +822,13 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
}
private void configureScreen() {
Point size = new Point();
mWindowManager.getDefaultDisplay().getSize(size);
mScreenWidth = size.x;
mScreenHeight = size.y;
DisplayMetrics realDm = new DisplayMetrics();
mWindow.getWindowManager().getDefaultDisplay().getRealMetrics(realDm);
mScreenWidth = realDm.widthPixels;
mScreenHeight = realDm.heightPixels;
Resources res = getResources();
int sb_height = 0;
int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
sb_height = res.getDimensionPixelSize(resourceId);
}
mScreenHeight -= sb_height;
SystemBarTintManager.SystemBarConfig config = mScreen.getSystemBarTintManager().getConfig();
mScreenHeight -= config.getStatusBarHeight() + config.getNavigationBarHeight();
mWorkspaceView.setLayoutParams(new FrameLayout.LayoutParams(mScreenWidth, mScreenHeight));
@ -962,8 +1001,8 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
}
@Override
public Identity getIdentity() {
return Identity.FLOATING;
public ScreenIdentity getIdentity() {
return ScreenIdentity.FLOATING;
}
@Override
@ -993,5 +1032,10 @@ public class WindowService extends Service implements LightningEngine.GlobalConf
}
}
@Override
public void onSystemBarsSizeChanged() {
configureScreen();
}
}
}

View file

@ -11,12 +11,13 @@ import java.io.File;
import java.util.HashMap;
public class Script extends JsonLoader {
public static final int NO_ID = -1;
public static final int NO_ID = net.pierrox.lightning_launcher.api.Script.NO_ID;
public static final int TYPE_FILE = 0;
public static final int TYPE_BUILTIN = 1;
public static final int TYPE_TARGET = 2;
public static final int TYPE_SET_VARIABLE = 3;
public static final int TYPE_IN_MEMORY = 4;
public static final int TARGET_NONE = -1;
public static final int TARGET_DESKTOP = 0;
@ -24,11 +25,11 @@ public class Script extends JsonLoader {
public static final int TARGET_LOCK_SCREEN = 2;
public static final int TARGET_BACKGROUND = 3;
public static final int FLAG_ALL = 0;
public static final int FLAG_DISABLED = 1;
public static final int FLAG_APP_MENU = 2;
public static final int FLAG_ITEM_MENU = 4;
public static final int FLAG_CUSTOM_MENU = 8;
public static final int FLAG_ALL = net.pierrox.lightning_launcher.api.Script.FLAG_ALL;
public static final int FLAG_DISABLED = net.pierrox.lightning_launcher.api.Script.FLAG_DISABLED;
public static final int FLAG_APP_MENU = net.pierrox.lightning_launcher.api.Script.FLAG_APP_MENU;
public static final int FLAG_ITEM_MENU = net.pierrox.lightning_launcher.api.Script.FLAG_ITEM_MENU;
public static final int FLAG_CUSTOM_MENU = net.pierrox.lightning_launcher.api.Script.FLAG_CUSTOM_MENU;
// public fields use for JSON serialization
public int id = Script.NO_ID;

View file

@ -344,6 +344,7 @@ public class ScriptExecutor {
public void onClick(DialogInterface dialogInterface, int i) {
mCurrentScriptDialog = false;
mCurrentScript.setFlag(Script.FLAG_DISABLED, true);
Toast.makeText(context, R.string.sc_disable_toast, Toast.LENGTH_LONG).show();
}
});
builder.setCancelable(false);
@ -406,6 +407,7 @@ public class ScriptExecutor {
public void onClick(DialogInterface dialogInterface, int i) {
mCurrentScriptDialog = false;
script.setFlag(Script.FLAG_DISABLED, true);
Toast.makeText(context, R.string.sc_disable_toast, Toast.LENGTH_LONG).show();
continuePendingContinuation(pending, input == null ? false : null);
}
});
@ -671,7 +673,18 @@ public class ScriptExecutor {
if(!canRunScript(script)) {
return null;
}
return runScriptAsFunction(screen, script, parameters, arguments, allow_continuation, display_errors);
}
public Object runScriptAsFunction(Screen screen, String code, String parameters, Object[] arguments, boolean allow_continuation, boolean display_errors) {
if(!canRunScriptGlobally()) {
return null;
}
Script script = new Script(mEngine.getScriptManager(), Script.TYPE_IN_MEMORY, Script.NO_ID, null, code, null);
return runScriptAsFunction(screen, script, parameters, arguments, allow_continuation, display_errors);
}
private Object runScriptAsFunction(Screen screen, Script script, String parameters, Object[] arguments, boolean allow_continuation, boolean display_errors) {
mCurrentScript = script;
if(mCurrentScript != null && !mCurrentScript.hasFlag(Script.FLAG_DISABLED)) {
prepareScriptScope();

View file

@ -42,25 +42,26 @@ public class ScriptManager {
BUILTINS = new Script[] {
new Script(this, Script.TYPE_BUILTIN, BUILTIN_USER_MENU, null,
"var item = LL.getEvent().getItem();\n"+
"LL.runAction(EventHandler.CLOSE_TOPMOST_FOLDER);\n"+
"var item = getEvent().getItem();\n"+
"var screen = getEvent().getScreen();\n"+
"screen.runAction(EventHandler.CLOSE_TOPMOST_FOLDER);\n"+
"switch(item.getName()) {\n"+
" case 'wallpaper': LL.runAction(EventHandler.SELECT_WALLPAPER); break;\n"+
" case 'wallpaper': screen.runAction(EventHandler.SELECT_WALLPAPER); break;\n"+
" case 'theme': " +
" var intent=new Intent(Intent.ACTION_VIEW, Uri.parse('"+ Version.BROWSE_TEMPLATES_URI+"'));"+
" var intent=new Intent(Intent.ACTION_VIEW, Uri.parse('"+ Version.BROWSE_TEMPLATES_URI+"'));\n"+
" intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n"+
" LL.startActivity(intent);\n"+
" screen.startActivity(intent);\n"+
" break;\n"+
" case 'add_item': LL.runAction(EventHandler.ADD_ITEM); break;\n"+
" case 'edit_layout': LL.runAction(EventHandler.EDIT_LAYOUT); break;\n"+
" case 'settings': LL.runAction(EventHandler.CUSTOMIZE_LAUNCHER); break;\n"+
" case 'add_item': screen.runAction(EventHandler.ADD_ITEM); break;\n"+
" case 'edit_layout': screen.runAction(EventHandler.EDIT_LAYOUT); break;\n"+
" case 'settings': screen.runAction(EventHandler.CUSTOMIZE_LAUNCHER); break;\n"+
"}",
null
),
new Script(this, Script.TYPE_BUILTIN, BUILTIN_REPOSITORY_IMPORTER, null,
"/*Script necessary for the repository importer to work correctly.*/\n" +
"\n" +
"eval(\"function toEval(){\\n\"+LL.loadRawResource(\"com.trianguloy.llscript.repository\",\"executor\")+\"\\n}\");\n" +
"eval(\"function toEval(){\\n\"+loadRawResource(\"com.trianguloy.llscript.repository\",\"executor\")+\"\\n}\");\n" +
"toEval();",
null
)

View file

@ -6,7 +6,7 @@ import android.widget.Toast;
/**
* The Android object gives access to some platform services.
* @deprecated use the android.widget.Toast class instead
* @deprecated use the android.widget.Toast class directly or the {@link Lightning#toast(String)} alternative instead
*/
public class Android {

View file

@ -2,6 +2,7 @@ package net.pierrox.lightning_launcher.script.api;
/**
* A binding links a "target" (a property) with a "formula" (a value).
* An instance of this object can be created with {@link #Binding(String, String, boolean)}; or retrieved with {@link Item#getBindingByTarget(String)} or {@link Item#getBindings()}.
*/
public class Binding {
private boolean enabled;

View file

@ -24,6 +24,8 @@ import net.pierrox.lightning_launcher.data.Utils;
* <li>Content:<b>c</b></li>
* </ul>
*
* An instance of this object can be retrieved with {@link PropertyEditor#getBox(String)} or {@link PropertySet#getBox(String)}.
*
* Example of using the Box object to change item properties:
* <pre>
* var color = 0xff00ff00; // pure green

View file

@ -7,15 +7,13 @@ import android.view.ViewGroup;
import com.faendir.rhino_android.RhinoAndroidHelper;
import java.util.ArrayList;
import java.util.HashMap;
import net.pierrox.lightning_launcher.R;
import net.pierrox.lightning_launcher.data.EmbeddedFolder;
import net.pierrox.lightning_launcher.data.IconPack;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.engine.LightningEngine;
import net.pierrox.lightning_launcher.script.api.screen.Screen;
import net.pierrox.lightning_launcher.views.ItemLayout;
import net.pierrox.lightning_launcher.views.item.ItemView;
@ -25,8 +23,13 @@ import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import java.util.ArrayList;
import java.util.HashMap;
/**
* The container can be either a desktop, a folder or a panel. Its role is to manage items inside.
*
* An instance of this object can be retrieved with {@link Event#getContainer()}, {@link Item#getParent()}, {@link Folder#getContainer()}, {@link Panel#getContainer()}, {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContainerById(int)}, {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getAllContainersById(int)} or {@link Screen#getFocusedContainer()}; or by using directly the special variable 'container' (which is the current Container) when running a 'Menu' event.
*/
public class Container {
public static final int NONE = Page.NONE;

View file

@ -2,10 +2,14 @@ package net.pierrox.lightning_launcher.script.api;
import android.view.View;
import net.pierrox.lightning_launcher.script.api.screen.Screen;
import net.pierrox.lightning_launcher.views.item.CustomViewView;
import net.pierrox.lightning_launcher.views.item.ItemView;
/**
* A CustomView is an advance special item that can display any Android View.
*
* An instance of this object can be retrieved with {@link Container#addCustomView(float, float)}; or with any function that returns an {@link Item} when that returned item is a CustomView; or by using directly the special variable 'item' (which is the current CustomView) when running a 'Create/Destroy script' event.
*/
public class CustomView extends Item {
/**
* @hide

View file

@ -6,6 +6,8 @@ import net.pierrox.lightning_launcher.views.ItemLayout;
/**
* The desktop is a kind of container, and is typically displayed as the home screen.
* It includes all capabilities of the base container, plus some other ones specific to desktops.
*
* An instance of this object can be retrieved with any function that returns a {@link Container} when that returned container is a Desktop; or with {@link net.pierrox.lightning_launcher.script.api.screen.HomeScreen#getDesktopByName(String)} or {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getCurrentDesktop()}.
*/
public class Desktop extends Container {

View file

@ -9,7 +9,7 @@ import net.pierrox.lightning_launcher.views.item.ItemView;
/**
* The event gather useful data dealing with the context of the event, such as which item caused the script to be executed, or what was the container at time of the event.
* @see LL#getEvent().
* An instance of this object can be retrieved with {@link Lightning#getEvent_()}.
*/
public class Event {
@ -120,7 +120,7 @@ public class Event {
}
/**
* Optional data that may have passed to this script when run from {@link LL#runScript(String, String)}.
* Optional data that may have passed to this script when run from {@link Screen#runScript(String, String)}.
*/
public String getData() {
return mData;

View file

@ -6,6 +6,8 @@ import net.pierrox.lightning_launcher.data.EventAction;
* Describe an event handler made of an action, some optional data and possibly a handler to execute after this one.
* Handlers are chained in a linked list. The last handler in the list has no next.
* When modifying an EventHandler acquired from {@link PropertySet#getEventHandler(String)}, you still need to call {@link PropertyEditor#setEventHandler(String, EventHandler)} to save changes.
*
* An instance of this object can be created with {@link #EventHandler(int, String)}; or retrieved with {@link PropertySet#getEventHandler(String)}.
*/
public class EventHandler {
public static final int UNSET=0;

View file

@ -3,7 +3,6 @@ package net.pierrox.lightning_launcher.script.api;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import net.pierrox.lightning_launcher.data.*;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.views.FolderView;
import net.pierrox.lightning_launcher.views.ItemLayout;
@ -13,6 +12,8 @@ import java.io.File;
/**
* The folder item extends the shortcut (because it have a label and an icon) and add folder specific services such as open/close.
*
* An instance of this object can be retrieved with any function that returns a {@link Shortcut} when that returned shortcut is a Folder; or with {@link Container#addFolder(String, float, float)} or {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getOpenFolders()}.
*/
public class Folder extends Shortcut {

View file

@ -28,6 +28,8 @@ import java.lang.reflect.Field;
* Utility class to manipulate images (icons, backgrounds, etc.).
* This is the base class for various kind of images. Each image type (bitmap, nine patch, animation, scripted) have their own set of features.
* Please refer to their respective documentation.
*
* An instance of this object can be created with {@link #createImage(String)}, {@link #createImage(String, String)}, {@link #fromDrawable(Lightning, Drawable, Item, File)}; or retrieved with {@link Folder#getWindowBackground()}, {@link net.pierrox.lightning_launcher.script.api.Item#getBoxBackground(String)}, {@link Shortcut#getDefaultIcon()}, {@link Shortcut#getCustomIcon()}, {@link Shortcut#getImage()}, {@link Shortcut#getIconLayer(String)} or {@link net.pierrox.lightning_launcher.script.api.screen.ActivityScreen#pickImage(int)}.
*/
public abstract class Image {
protected Lightning mLightning;
@ -264,7 +266,7 @@ public abstract class Image {
/**
* Create an image from a package and a resource name.
* For instance:<code>LL.createImage("net.pierrox.lightning_launcher_extreme", "icon")</code>
* For instance:<code>Image.createImage("net.pierrox.lightning_launcher_extreme", "icon")</code>
* The density used is either the one given by ActivityManager.getLauncherLargeIconDensity if available, or the current one.
* @param pkg name of the package, use "android" to access system resources.
* @param name name of the drawable resource

View file

@ -12,6 +12,8 @@ import java.io.File;
* A kind of image which can play an animation (often loaded from GIF files).
*
* <b>Note</b>: as of today backgrounds and icon layers do not support animations, only the first frame will be displayed.
*
* An instance of this object can be created with {@link Image#createAnimation(int, int, int, int, int)}; or retrieved with any function that returns an {@link Image} when that image is an ImageAnimation.
*/
public class ImageAnimation extends Image {
private SharedAsyncGraphicsDrawable mDrawable;

View file

@ -2,12 +2,11 @@ package net.pierrox.lightning_launcher.script.api;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.engine.*;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.views.SharedAsyncGraphicsDrawable;
import net.pierrox.lightning_launcher.views.item.ItemView;
@ -18,7 +17,9 @@ import java.io.IOException;
/**
* Wraps a static bitmap.
* Such an image can be loaded from file, created using {@link LL#createImage(int, int)}, or obtained from items icons.
* Such an image can be loaded from file, created using {@link Image#createImage(int, int)}, or obtained from items icons.
*
* An instance of this object can be created with {@link Image#createImage(int, int)} or {@link Image#createTextIcon(String, int, int, int, Typeface)}; or retrieved with any function that returns an {@link Image} when that image is an ImageBitmap; or with {@link ImageAnimation#getFrameImage(int)} or {@link net.pierrox.lightning_launcher.script.api.screen.ActivityScreen#cropImage(ImageBitmap, boolean)}.
*/
public class ImageBitmap extends Image {
private Bitmap mBitmap;
@ -101,7 +102,7 @@ public class ImageBitmap extends Image {
* <ul>
* <li>{@link net.pierrox.lightning_launcher.script.api.Shortcut#getDefaultIcon()}</li>
* <li>{@link net.pierrox.lightning_launcher.script.api.Shortcut#getCustomIcon()}</li>
* <li>{@link net.pierrox.lightning_launcher.script.api.LL#createImage(String)}</li>
* <li>{@link Image#createImage(String)}</li>
* Calling this method on an image without source file will do nothing.
*/
public void save() {

View file

@ -6,6 +6,8 @@ import android.graphics.drawable.NinePatchDrawable;
/**
* Wraps a Nine Patch image.
*
* An instance of this object can be retrieved with any function that returns an {@link Image} when that image is an ImageNinePatch.
*/
public class ImageNinePatch extends Image {

View file

@ -12,7 +12,8 @@ import org.mozilla.javascript.Scriptable;
/**
* ImageScript is a way to draw images or animations without the need for intermediate bitmaps.
* Such images are scalable and memory efficient.
* Instances of ImageScript can be created with {@link LL#createImage(Scriptable, int, int)}.
*
* An instance of this object can be created with {@link Image#createImage(Scriptable, int, int)}; or retrieved with any function that returns an {@link Image} when that image is an ImageScript.
*
* The Scriptable object must have a "draw" function, and optionally a "pause" and "resume" functions. These functions are called with a DrawingContext instance.
* <br/><br/>
@ -20,7 +21,7 @@ import org.mozilla.javascript.Scriptable;
* <br/><br/>
* Sample 1 : draw a static image.
* <code><pre>
* var img = LL.createImage({
* var img = Image.createImage({
* draw: function(context) {
* var canvas = context.getCanvas();
* var w = context.getWidth();
@ -88,7 +89,7 @@ import org.mozilla.javascript.Scriptable;
* timers: {}
* };
*
* var img = LL.createImage(drawing, -1, -1);
* var img = Image.createImage(drawing, -1, -1);
* </pre></code>
*/
public class ImageScript extends Image {

View file

@ -7,6 +7,8 @@ import net.pierrox.android.lsvg.SvgDrawable;
/**
* An image backed by a SVG document
*
* An instance of this object can be retrieved with any function that returns an {@link Image} when that image is an ImageSvg.
*/
public class ImageSvg extends Image {

View file

@ -1,10 +1,6 @@
package net.pierrox.lightning_launcher.script.api;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.graphics.Bitmap;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@ -13,9 +9,10 @@ import android.widget.TextView;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.configuration.ItemConfig;
import net.pierrox.lightning_launcher.data.*;
import net.pierrox.lightning_launcher.data.Box;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.data.Shortcut;
import net.pierrox.lightning_launcher.data.Utils;
import net.pierrox.lightning_launcher.script.api.screen.Screen;
import net.pierrox.lightning_launcher.views.IconLabelView;
import net.pierrox.lightning_launcher.views.ItemLayout;
@ -27,6 +24,10 @@ import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* The item is the base class for other objects that can be found in a container (shortcuts, folders, etc.).
* There are specific classes for some items (shortcut, folder, ...) when these items provides custom services.
@ -34,6 +35,8 @@ import org.mozilla.javascript.Scriptable;
*
* Since Lightning V14 allows the same container to be displayed multiple times on the same screen, it is possible to retrieve
* several Item objects linked with the same underlying data. The identifier (see {@link #getId()}) will then be the same.
*
* An instance of this object can be retrieved with {@link Event#getItem()}, {@link Screen#getItemById(int)}, {@link Screen#getAllItemsById(int)}, {@link Container#getAllItems()}, {@link Container#getItemById(int)}, {@link Container#getItemByName(String)}, {@link Container#cloneItem(Item)}, {@link Container#moveItem(Item, Container)}, {@link Container#getOpener()} or {@link ImageScript.DrawingContext#getItem()}; or by using directly the special variable 'item' (which is the current Item) when running a 'Menu' event.
*/
public class Item {
@ -62,6 +65,10 @@ public class Item {
return object;
}
/**
* Return the Screen where this item is placed.
* @return the screen containing this item
*/
public Screen getScreen() {
return mLightning.createScreen(mItemView.getParentItemLayout().getScreen());
}

View file

@ -2,21 +2,21 @@ package net.pierrox.lightning_launcher.script.api;
import android.content.Context;
import android.content.Intent;
import net.dinglisch.android.tasker.TaskerIntent;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.script.api.screen.ActivityScreen;
import net.pierrox.lightning_launcher.script.api.screen.HomeScreen;
import net.pierrox.lightning_launcher.views.ItemLayout;
import org.mozilla.javascript.Scriptable;
/**
* The main object to access Lightning Launcher features.
* The LL object gives access to desktops, items or give contextual data on the event.
* @deprecated use {@link Lightning} instead.
*
* @deprecated check alternatives on each function.
*/
public class LL {
private Lightning mLightning;
@ -32,12 +32,15 @@ public class LL {
/**
* Returns the currently displayed desktop.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getCurrentDesktop()} instead together with {@link Lightning#getActiveScreen()}
* <br><code>LL.getCurrentDesktop() -> getActiveScreen().getCurrentDesktop()</code>
*/
public Desktop getCurrentDesktop() {
int id = mLightning.getEngine().readCurrentPage(mLightning.getConfiguration().getHomeDesktopId());
Screen screen = LLApp.get().getScreen(Screen.Identity.HOME);
Screen screen = LLApp.get().getScreen(ScreenIdentity.HOME);
if(screen == null) {
screen = LLApp.get().getScreen(Screen.Identity.BACKGROUND);
screen = LLApp.get().getScreen(ScreenIdentity.BACKGROUND);
}
screen.loadRootItemLayout(id, false, false, true);
@ -48,12 +51,16 @@ public class LL {
/**
* Returns the home desktop.
* As of Lightning V14, this method looks for the desktop in the home screen, then in the background desktop.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContainerById(int)} instead together with {@link Configuration#getHomeDesktopId()}
* <br><code>LL.getHomeDesktop() -> getHomeScreen().getContainerById(getConfiguration().getHomeDesktopId())</code>
* (note: in some rare cases {@link Lightning#getHomeScreen()} may return null. If necessary consider searching on {@link Lightning#getBackgroundScreen()} as an alternative)
*/
public Desktop getHomeDesktop() {
int id = mLightning.getConfiguration().getHomeDesktopId();
Screen screen = LLApp.get().getScreen(Screen.Identity.HOME);
Screen screen = LLApp.get().getScreen(ScreenIdentity.HOME);
if(screen == null) {
screen = LLApp.get().getScreen(Screen.Identity.BACKGROUND);
screen = LLApp.get().getScreen(ScreenIdentity.BACKGROUND);
}
screen.loadRootItemLayout(id, false, false, true);
@ -64,6 +71,10 @@ public class LL {
/**
* Returns the desktop used as the lock screen, or null if not set.
* As of Lightning V14, this method looks for the desktop in the lock screen, then in the home screen, and finally in the background desktop.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContainerById(int)} instead together with {@link Configuration#getLockscreenDesktopId()}
* <br><code>LL.getLockscreenDesktop() -> getLockScreen().getContainerById(getConfiguration().getLockscreenDesktopId())</code>
* (note: in most cases {@link Lightning#getLockScreen()} may return null. If necessary consider searching on {@link Lightning#getHomeScreen()} or {@link Lightning#getBackgroundScreen()} as an alternative)
*/
public Desktop getLockscreenDesktop() {
int id = mLightning.getConfiguration().getLockscreenDesktopId();
@ -71,11 +82,11 @@ public class LL {
return null;
}
Screen screen = LLApp.get().getScreen(Screen.Identity.LOCK);
Screen screen = LLApp.get().getScreen(ScreenIdentity.LOCK);
if(screen == null) {
screen = LLApp.get().getScreen(Screen.Identity.HOME);
screen = LLApp.get().getScreen(ScreenIdentity.HOME);
if(screen == null) {
screen = LLApp.get().getScreen(Screen.Identity.BACKGROUND);
screen = LLApp.get().getScreen(ScreenIdentity.BACKGROUND);
}
}
@ -86,6 +97,9 @@ public class LL {
/**
* Returns the desktop used as the floating desktop, or null if not set.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContainerById(int)} instead together with {@link Configuration#getFloatingDesktopId()}
* <br><code>LL.getFloatingDesktop(); -> getFloatingScreen().getContainerById(getConfiguration().getFloatingDesktopId())</code>
*/
public Desktop getFloatingDesktop() {
int id = mLightning.getConfiguration().getFloatingDesktopId();
@ -93,7 +107,7 @@ public class LL {
return null;
}
Screen screen = LLApp.get().getScreen(Screen.Identity.FLOATING);
Screen screen = LLApp.get().getScreen(ScreenIdentity.FLOATING);
if(screen == null) {
return null;
}
@ -104,6 +118,10 @@ public class LL {
/**
* Returns an array of desktop identifiers.
*
* @deprecated use {@link Configuration#getAllDesktops()} instead together with {@link Lightning#getConfiguration()}
* (Difference: returns a java array instead of {@link Array}, convert if necessary)
* <br><code>LL.getAllDesktops() ~> getConfiguration().getAllDesktops()</code>
*/
public Array getAllDesktops() {
int[] so = mLightning.getConfiguration().getAllDesktops();
@ -117,14 +135,16 @@ public class LL {
/**
* Returns a container by its id.
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContainerById(int)}
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContainerById(int)} instead with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.getContainerById(id) -> getEvent().getScreen().getContainerById(id)</code>
*/
public Container getContainerById(int id) {
Screen screen;
if(id == Page.APP_DRAWER_PAGE) {
screen = LLApp.get().getScreen(Screen.Identity.APP_DRAWER);
screen = LLApp.get().getScreen(ScreenIdentity.APP_DRAWER);
if(screen == null) {
screen = LLApp.get().getScreen(Screen.Identity.BACKGROUND);
screen = LLApp.get().getScreen(ScreenIdentity.BACKGROUND);
}
return mLightning.createScreen(screen).getContainerById(id);
} else {
@ -137,9 +157,12 @@ public class LL {
* This method will return null if no desktop by that name can be found
*
* @param name name of the desktop
*
* @deprecated use {@link HomeScreen#getDesktopByName(String)} instead together with {@link Lightning#getHomeScreen()}
* <br><code>LL.getDesktopByName(name) -> getHomeScreen().getDesktopByName(name)</code>
*/
public Desktop getDesktopByName(String name) {
Screen dashboardScreen = LLApp.get().getScreen(Screen.Identity.HOME);
Screen dashboardScreen = LLApp.get().getScreen(ScreenIdentity.HOME);
if(dashboardScreen != null) {
return new HomeScreen(mLightning, dashboardScreen).getDesktopByName(name);
} else {
@ -149,7 +172,11 @@ public class LL {
/**
* Go to a specified desktop, without changing the current position in this desktop.
*
* @param id desktop identifier
*
* @deprecated use {@link HomeScreen#goToDesktop(int)} instead together with {@link Lightning#getHomeScreen()}
* <br><code>LL.goToDesktop(id) -> getHomeScreen().goToDesktop(id)</code>
*/
public void goToDesktop(int id) {
LLApp.get().displayPagerPage(id, false);
@ -157,9 +184,13 @@ public class LL {
/**
* Go to a specified desktop and set the current absolute position in this desktop, setting a scale of 1 and using animations. This method does nothing when the script is run in background.
*
* @param id desktop identifier
* @param x absolute X position, in pixel
* @param y absolute Y position, in pixel
*
* @deprecated use {@link HomeScreen#goToDesktopPosition(int, float, float)} instead together with {@link Lightning#getHomeScreen()}
* <br><code>LL.goToDesktopPosition(id, x, y) -> getHomeScreen().goToDesktopPosition(id, x, y)</code>
*/
public void goToDesktopPosition(int id, float x, float y) {
goToDesktopPosition(id, x, y, 1, true);
@ -167,21 +198,27 @@ public class LL {
/**
* Go to a specified desktop and set the current absolute position in this desktop. This method does nothing when the script is run in background.
*
* @param id desktop identifier
* @param x absolute X position, in pixel
* @param y absolute Y position, in pixel
* @param scale zoom factor (1=100%, 0.5=50%, negative values are acceptable, 0 is not very useful)
* @param animate whether to animate the move
*
* @deprecated use {@link HomeScreen#goToDesktopPosition(int, float, float, float, boolean)} instead together with {@link Lightning#getHomeScreen()}
* <br><code>LL.goToDesktopPosition(id, x, y, scale, animate) -> getHomeScreen().goToDesktopPosition(id, x, y, scale, animate)</code>
*/
public void goToDesktopPosition(int id, float x, float y, float scale, boolean animate) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getScriptScreen();
screen.getScreen().goToDesktopPosition(id, -x * scale, -y * scale, scale, animate);
screen.getScreen().goToDesktopPosition(id, -x * scale, -y * scale, scale, animate, true);
}
/**
* Returns the event object associated with this script execution.
* The event provides contextual data, such as the current desktop, which item has been tapped, and so on.
* @deprecated use {@link Lightning#getEvent_()}
*
* @deprecated use {@link Lightning#getEvent_()} instead
* <br><code>LL.getEvent() -> getEvent()</code>
*/
public Event getEvent() {
return mLightning.findEventInStack();
@ -191,6 +228,9 @@ public class LL {
/**
* Same as #runAction(int,String) with a null data.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#runAction(int)} instead together with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.runAction(action) -> getEvent().getScreen().runAction(action)</code>
*/
public void runAction(int action) {
mLightning.getScriptScreen().runAction(action);
@ -198,6 +238,9 @@ public class LL {
/**
* Same as #runAction(int,Item,String) with a null item and data.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#runAction(int, String)} instead together with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.runAction(action, data) -> getEvent().getScreen().runAction(action, data)</code>
*/
public void runAction(int action, String data) {
mLightning.getScriptScreen().runAction(action, data);
@ -205,9 +248,13 @@ public class LL {
/**
* Run a Lightning action. This method does nothing when the script is run in background.
*
* @param action action code (one of the values defined in {@link net.pierrox.lightning_launcher.script.api.EventHandler}
* @param item item to be used as the target (only useful with actions requiring an item)
* @param data optional data to send to be used by the action, use null if none
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#runAction(int, Item, String)} instead together with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.runAction(action, item, data) -> getEvent().getScreen().runAction(action, item, data)</code>
*/
public void runAction(int action, Item item, String data) {
mLightning.getScriptScreen().runAction(action, item, data);
@ -216,23 +263,28 @@ public class LL {
/**
* Run another script.
* Optional data can be transmitted to the called script and retrieved using {@link Event#getData()}.
*
* @param name name of the script as found in the script editor
* @param data optional data to send to the script. Use JSON to pass more than a string.
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#runScript(String, String)}
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#runScript(String, String)} instead together with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.runScript(name, data) -> getEvent().getScreen().runScript(name, data)</code>
*/
public void runScript(final String name, final String data) {
mLightning.getScriptScreen().runScript(name, data);
}
/**
* @deprecated use Script#setTag(String) instead together with #getCurrentScript
* @deprecated use {@link Script#setTag(String)} instead together with {@link Lightning#getCurrentScript()}
* <br><code>LL.setScriptTag(tag) -> getCurrentScript().setTag(tag)</code>
*/
public void setScriptTag(String tag) {
getCurrentScript().setTag(tag);
}
/**
* @deprecated use Script#getTag() instead
* @deprecated use {@link Script#getTag()} instead together with {@link Lightning#getCurrentScript()}
* <br><code>LL.getScriptTag() -> getCurrentScript().getTag()</code>
*/
public String getScriptTag() {
return getCurrentScript().getTag();
@ -240,6 +292,9 @@ public class LL {
/**
* Retrieve the currently executed script.
*
* @deprecated use {@link Lightning#getCurrentScript()} instead
* <br><code>LL.getCurrentScript() -> getCurrentScript()</code>
*/
public Script getCurrentScript() {
return mLightning.getCurrentScript();
@ -247,8 +302,12 @@ public class LL {
/**
* Retrieve a script by name
*
* @param name as given by Script#getName()
* @return a script or null if not found
*
* @deprecated use {@link Lightning#getScriptByName(String)} instead
* <br><code>LL.getScriptByName(name) -> getScriptByName(name)</code>
*/
public Script getScriptByName(String name) {
return mLightning.getScriptByName(name);
@ -256,8 +315,12 @@ public class LL {
/**
* Retrieve a script by its unique identifier
*
* @param id identifier as given by Script#getId()
* @return a script or null if no script with this id
*
* @deprecated use {@link Lightning#getScriptById(String)} instead
* <br><code>LL.getScriptById(id) -> getScriptById(id)</code>
*/
public Script getScriptById(String id) {
return mLightning.getScriptById(id);
@ -265,6 +328,9 @@ public class LL {
/**
* Delete a script.
*
* @deprecated use {@link Lightning#deleteScript(Script)} instead
* <br><code>LL.deleteScript(script) -> deleteScript(script)</code>
*/
public void deleteScript(Script script) {
mLightning.deleteScript(script);
@ -272,6 +338,9 @@ public class LL {
/**
* Create a new script. Use this API wisely.
*
* @deprecated use {@link Lightning#createScript(String, String, int)} instead
* <br><code>LL.createScript(name, text, flags) -> createScript(name, text, flags)</code>
*/
public Script createScript(String name, String text, int flags) {
return mLightning.createScript(name, text, flags);
@ -280,6 +349,10 @@ public class LL {
/**
* Return the collection of scripts matching some flags.
* @param flags see Script#FLAG_*
*
* @deprecated use {@link Lightning#getAllScriptMatching(int)}
* (Difference: returns a java array instead of {@link Array}, convert if necessary)
* <br><code>LL.getAllScriptMatching(flags) ~> getAllScriptMatching(flags)</code>
*/
public Array getAllScriptMatching(int flags) {
Script[] array = mLightning.getAllScriptMatching(flags);
@ -288,6 +361,9 @@ public class LL {
/**
* Unlock the screen.
*
* @deprecated use {@link Lightning#unlock()} instead
* <br><code>LL.unlock() -> unlock()</code>
*/
public void unlock() {
mLightning.unlock();
@ -295,16 +371,23 @@ public class LL {
/**
* Returns true if the screen is currently locked using the Lightning lock screen.
*
* @deprecated use {@link Lightning#isLocked()} instead
* <br><code>LL.isLocked() -> isLocked()</code>
*/
public boolean isLocked() {
return mLightning.isLocked();
}
/**
* Write data to a file. This is for logging and debug purpose only. The path is not configurable and is: <external storage>/LightningLauncher/script/log.txt.
* Write data to a file. This is for logging and debug purpose only. The path is not configurable and is: {@literal <}external storage{@literal >}/LightningLauncher/script/log.txt.
* Please note that this method won't add newlines automatically when appending data.
*
* @param data text to write to the file
* @param append whether to clear the file before to write data, or append data to the existing content
*
* @deprecated use {@link Lightning#writeToLogFile(String, boolean)} instead
* <br><code>LL.writeToLogFile(data, append) -> writeToLogFile(data, append)</code>
*/
public void writeToLogFile(String data, boolean append) {
mLightning.writeToLogFile(data, append);
@ -313,6 +396,10 @@ public class LL {
/**
* Returns whether the current context is paused. It often means that Lightning Launcher is not displayed, for instance because another app is running.
* When the script is executed in the background this method always returns true.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#isPaused()} instead together with {@link Lightning#getHomeScreen()}
* (difference: this function returns false if any screen is not paused, not only the HomeScreen. For an exact substitute check all the other screens too)
* <br><code>LL.isPaused(tag) ~> getHomeScreen().isPaused()</code>
*/
public boolean isPaused() {
boolean paused = true;
@ -328,7 +415,12 @@ public class LL {
/**
* Returns the list of currently open folders. This function returns the opener item, not the container itself.
* This method will return null when the script is executed in the background.
*
* @return an Array of Folder items, sorted top to bottom (topmost folder is at index 0).
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getOpenFolders()} instead together with {@link Lightning#getActiveScreen()}
* (Difference: returns a java array instead of {@link Array}, convert if necessary)
* <br><code>LL.getOpenFolders() ~> getActiveScreen().getOpenFolders()</code>
*/
public Array getOpenFolders() {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -341,9 +433,12 @@ public class LL {
/**
* Returns an item by its id. This is a shortcut avoiding to traverse the list of all desktops and folders.
*
* @param id item identifier
* @return an item, or null if this id is not known.
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getItemById(int)}
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getItemById(int)} instead together with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.getItemById(id) -> getEvent().getScreen().getItemById(id)</code>
*/
public Item getItemById(int id) {
return mLightning.getScriptScreen().getItemById(id);
@ -352,7 +447,11 @@ public class LL {
/**
* Create a blank new image of the specified size. Pixel format is always ARGB 8888.
* Take care when creating images since it can rapidly exhaust memory and lead to a crash.
*
* @return can return null if not enough memory
*
* @deprecated use {@link Image#createImage(int, int)} instead
* <br><code>LL.createImage(width, height) -> Image.createImage(width, height)</code>
*/
public ImageBitmap createImage(int width, int height) {
return Image.createImage(width, height);
@ -360,8 +459,12 @@ public class LL {
/**
* Create an image from the specified file.
*
* @param path path of the image
* @return can return null if an image cannot be read from the file (not an image or not enough memory)
*
* @deprecated use {@link Image#createImage(String)} instead
* <br><code>LL.createImage(path) -> Image.createImage(path)</code>
*/
public Image createImage(String path) {
return Image.createImage(path);
@ -371,9 +474,13 @@ public class LL {
* Create an image from a package and a resource name.
* For instance: <code>LL.createImage("net.pierrox.lightning_launcher_extreme", "icon")</code>
* The density used is either the one given by ActivityManager.getLauncherLargeIconDensity if available, or the current one.
*
* @param pkg name of the package, use "android" to access system resources.
* @param name name of the drawable resource
* @return can return null if an image cannot be read from the package (unknown package, wrong resource name or not enough memory)
*
* @deprecated use {@link Image#createImage(String, String)} instead
* <br><code>LL.createImage(pkg, name) -> Image.createImage(pkg, name)</code>
*/
public Image createImage(String pkg, String name) {
return Image.createImage(pkg, name);
@ -387,6 +494,9 @@ public class LL {
* @param object the set of functions
* @param width the prefered image width, use -1 for as big as possible
* @param height the prefered image height, use -1 for as big as possible
*
* @deprecated use {@link Image#createImage(Scriptable, int, int)} instead
* <br><code>LL.createImage(object, width, height) -> Image.createImage(object, width, height)</code>
*/
public ImageScript createImage(Scriptable object, int width, int height) {
return Image.createImage(object, width, height);
@ -395,12 +505,16 @@ public class LL {
/**
* Create a blank animation: frames are created fully transparent and need to be drawn.
* Notes: animations created this way are memory expensive and cannot be persisted (yet). This means that Shortcut.setCustomIcon() wont't work, but Shortcut.setImage() will.
*
* @param width image width
* @param height image height
* @param count number of frames to allocate
* @param duration default frame duration
* @param loopCount initial number of loops to play, use 0 for infinite
* @return an animation or null in case of error (most likely out of memory)
*
* @deprecated use {@link Image#createAnimation(int, int, int, int, int)} instead
* <br><code>LL.createAnimation(width, height, count, duration, loopCount) -> Image.createAnimation(width, height, count, duration, loopCount)</code>
*/
public ImageAnimation createAnimation(int width, int height, int count, int duration, int loopCount) {
return Image.createAnimation(width, height, count, duration, loopCount);
@ -413,9 +527,13 @@ public class LL {
* <li>load scripts and set them as event handler (useful in script plugins)</li>
* <li>load JSON data, such as theme colors, data, etc.</li>
* </ul>
*
* @param pkg package name from which to read resources
* @param name name of the raw resource. It must not contain the extension of the raw file, this is the Android identifier.
* @return a string or null if the resource cannot be found or read
*
* @deprecated use {@link Lightning#loadRawResource(String, String)} instead
* <br><code>LL.loadRawResources(pkg, name) -> loadRawResources(pkg, name)</code>
*/
public String loadRawResource(String pkg, String name) {
return mLightning.loadRawResource(pkg, name);
@ -423,6 +541,9 @@ public class LL {
/**
* Persist launcher data now.
*
* @deprecated use {@link Lightning#save()} instead
* <br><code>LL.save() -> save()</code>
*/
public void save() {
mLightning.save();
@ -433,8 +554,12 @@ public class LL {
* Example:<code><pre>
* var intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.pierrox.net/")
* LL.startActivity(intent);</pre></code>
*
* @param intent intent to start the activity
* @return true if launch is successful, false if activity not found or permission denied
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#startActivity(Intent)} instead together with {@link Lightning#getActiveScreen()}
* <br><code>LL.startActivity(intent) -> getActiveScreen().startActivity(intent)</code>
*/
public boolean startActivity(Intent intent) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -450,10 +575,14 @@ public class LL {
* <li>token: String, optional value passed as third argument in startActivityForResult</li>
* </ul>
* This method cannot be called when the executing script is run in the background. In that case it will do nothing and return false
*
* @param intent intent to start the activity
* @param receiver a script to execute upon activity end
* @param token an optional string data that you can transmit to the receiver script
* @return true if the activity has been started
*
* @deprecated use {@link ActivityScreen#startActivityForResult(Intent, Script, String)} instead together with an {@link ActivityScreen}
* <br><code>LL.startActivityForResult(intent, receiver, token) -> 'startActivityForResult' in getActiveScreen() ? getActiveScreen().startActivityForResult(intent, receiver, token) : false</code>
*/
public boolean startActivityForResult(Intent intent, Script receiver, String token) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -466,9 +595,13 @@ public class LL {
/**
* Send a tasker intent, optionally waiting for its completion to return.
*
* @param intent an intent built with TaskerIntent (see http://tasker.dinglisch.net/invoketasks.html for samples)
* @param synchronous when true, Lightning will wait for Tasker task completion before to return, otherwise it will return immediately
* @return when synchronous is true returns true if the intent has been sent successfully and Tasker reports a success too, when synchronous is false this method always returns true..
*
* @deprecated use {@link Lightning#sendTaskerIntent(TaskerIntent, boolean)} instead
* <br><code>LL.sendTaskerIntent(intent, synchronous) -> sendTaskerIntent(intent, synchronous)</code>
*/
public boolean sendTaskerIntent(TaskerIntent intent, boolean synchronous) {
return mLightning.sendTaskerIntent(intent, synchronous);
@ -477,6 +610,9 @@ public class LL {
/**
* Return the Android Context this script is linked with (an activity context).
* This is meant to be used with Android services.
*
* @deprecated use {@link net.pierrox.lightning_launcher.script.api.screen.Screen#getContext()} instead with a {@link net.pierrox.lightning_launcher.script.api.screen.Screen}
* <br><code>LL.getContext() -> getActiveScreen().getContext()</code>
*/
public Context getContext() {
Screen screen = LLApp.get().getActiveScreen();
@ -490,8 +626,12 @@ public class LL {
/**
* Translate a Java class into a JavaScript object.
* This is a convenience method that avoid repeated use of fully qualified names while scripting Java.
*
* @param name fully qualified class name
* @return true if the operation succeeded, false if the class cannot be loaded or if already bound
*
* @deprecated use {@link Lightning#bindClass(String)} instead
* <br><code>LL.bindClass(name) -> bindClass(name)</code>
*/
public boolean bindClass(String name) {
return mLightning.getEngine().getScriptExecutor().bindClass(name);
@ -499,10 +639,14 @@ public class LL {
/**
* Request the user to pick a color.
*
* @param title text displayed at the top of the dialog
* @param color initial color to display
* @param hasAlpha whether to display the transparency slider. It will not enforce a fully opaque color, it only acts on the slider visibility.
* @return either the selected color, or undefined if the dialog has been canceled
*
* @deprecated use {@link ActivityScreen#pickColor(String, int, boolean)} instead together with an {@link ActivityScreen}
* <br><code>LL.pickColor(title, color, hasAlpha) -> 'pickColor' in getActiveScreen() ? getActiveScreen().pickColor(title, color, hasAlpha) : 0</code>
*/
public int pickColor(String title, int color, boolean hasAlpha) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -517,6 +661,7 @@ public class LL {
* Request the user to enter a numeric value.
* When using the "%" unit, valueType must be set to FLOAT: the dialog will scale a decimal value so that 0.75 is displayed as 75%.
* Warning: the returned value may be subject to rounding errors.
*
* @param title text displayed at the top of the dialog
* @param value initial value to display
* @param valueType either INT or FLOAT. It will default to FLOAT if valueType is not a known value.
@ -525,6 +670,9 @@ public class LL {
* @param interval interval between values when sliding
* @param unit text to display after the value (for instance "%" or "px"). When using "%" with FLOAT, scale value by 100
* @return either the selected value, or undefined if the dialog has been canceled
*
* @deprecated use {@link ActivityScreen#pickNumericValue(String, float, String, float, float, float, String)} instead together with an {@link ActivityScreen}
* <br><code>LL.pickNumericValue(title, value, valueType, min, max, interval, unit) -> 'pickNumericValue' in getActiveScreen() ? getActiveScreen().pickNumericValue(title, value, valueType, min, max, interval, unit) : 0</code>
*/
public float pickNumericValue(String title, float value, String valueType, float min, float max, float interval, String unit) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -540,8 +688,12 @@ public class LL {
* Warning: images returned by this function may be very large, take care at memory use as exceeding limits will make the launcher crash.
* Use the maxPixels parameter: the image will be scaled by a power of two so that its number of pixels is below or equal.
* This function supports picking bitmaps and nine patches.
*
* @param maxPixels maximum number of pixels in the returned image (width x height), 0 for no limit, 1048576 is one mega pixels (1024 x 1024)
* @return an {@link net.pierrox.lightning_launcher.script.api.Image}, or null if the user canceled the operation, or if the image cannot be loaded
*
* @deprecated use {@link ActivityScreen#pickImage(int)} instead together with an {@link ActivityScreen}
* <br><code>LL.pickImage(maxPixels) -> 'pickImage' in getActiveScreen() ? getActiveScreen().pickImage(maxPixels) : null</code>
*/
public Image pickImage(int maxPixels) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -555,9 +707,13 @@ public class LL {
/**
* Request the user to select an area in the image.
* Warning: because images need to be persisted to file while cropping, this method may be slow.
*
* @param image image to be cropped
* @param full_size handling big images can be slow or request too much memory, by setting full_size to false this will allow this method to downscale images (approx. the size of the screen)
* @return a cropped image, or null if the operation failed or the user canceled it
*
* @deprecated use {@link ActivityScreen#cropImage(ImageBitmap, boolean)} instead together with an {@link ActivityScreen}
* <br><code>LL.cropImage(image, full_size) -> 'cropImage' in getActiveScreen() ? getActiveScreen().cropImage(image, full_size) : null</code>
*/
public ImageBitmap cropImage(ImageBitmap image, boolean full_size) {
net.pierrox.lightning_launcher.script.api.screen.Screen screen = mLightning.getActiveScreen();
@ -570,6 +726,9 @@ public class LL {
/**
* Set a boolean variable. This is a shortcut for <code>LL.getVariables().edit().setBoolean(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*
* @deprecated use {@link Lightning#setVariableBoolean(String, boolean)} instead
* <br><code>LL.setVariableBoolean(name, value) -> setVariableBoolean(name, value)</code>
*/
public void setVariableBoolean(String name, boolean value) {
mLightning.setVariableBoolean(name, value);
@ -577,6 +736,9 @@ public class LL {
/**
* Set a boolean variable. This is a shortcut for <code>LL.getVariables().edit().setInteger(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*
* @deprecated use {@link Lightning#setVariableInteger(String, long)} instead
* <br><code>LL.setVariableInteger(name, value) -> setVariableInteger(name, value)</code>
*/
public void setVariableInteger(String name, long value) {
mLightning.setVariableInteger(name, (int)value);
@ -584,6 +746,9 @@ public class LL {
/**
* Set a boolean variable. This is a shortcut for <code>LL.getVariables().edit().setFloat(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*
* @deprecated use {@link Lightning#setVariableFloat(String, float)} instead
* <br><code>LL.setVariableFloat(name, value) -> setVariableFloat(name, value)</code>
*/
public void setVariableFloat(String name, float value) {
mLightning.setVariableFloat(name, value);
@ -591,6 +756,9 @@ public class LL {
/**
* Set a string variable. This is a shortcut for <code>LL.getVariables().edit().setString(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*
* @deprecated use {@link Lightning#setVariableString(String, String)} instead
* <br><code>LL.setVariableString(name, value) -> setVariableString(name, value)</code>
*/
public void setVariableString(String name, String value) {
mLightning.setVariableString(name, value);
@ -598,6 +766,9 @@ public class LL {
/**
* Retrieve the whole set of known variables (builtins and user ones).
*
* @deprecated use {@link Lightning#getVariables()} instead
* <br><code>LL.getVariables() -> getVariables()</code>
*/
public VariableSet getVariables() {
return mLightning.getVariables();

View file

@ -9,11 +9,13 @@ import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.util.SparseArray;
import android.widget.Toast;
import com.faendir.rhino_android.RhinoAndroidHelper;
import net.dinglisch.android.tasker.TaskerIntent;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.data.FileUtils;
import net.pierrox.lightning_launcher.data.Page;
import net.pierrox.lightning_launcher.engine.LightningEngine;
@ -41,8 +43,8 @@ import java.util.ArrayList;
/**
* Entry point for most Lightning Launcher scripted features.
* The Lightning object is the root object in the script context, hence its functions can be called without naming it, unlike with the deprecated LL object.
* For instance, instead of using <code>LL.getDesktopByName('d')</code>, simply use <code>getDesktopByName('d')</code>
* The Lightning object is the root object in the script context, hence its functions can be called without naming it (unlike the rest of the classes).
* For instance, instead of using <code style="color:#333">Lightning.alert('Hello World')</code>, simply use <code>alert('Hello World')</code>
*/
public class Lightning {
@ -300,46 +302,51 @@ public class Lightning {
* Return the home screen, null if not created yet
*/
public HomeScreen getHomeScreen() {
return (HomeScreen) createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.engine.Screen.Identity.HOME));
return (HomeScreen) createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.api.ScreenIdentity.HOME));
}
/**
* Return the app drawer screen, null if not created yet
*/
public ActivityScreen getAppDrawerScreen() {
return (ActivityScreen) createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.engine.Screen.Identity.APP_DRAWER));
return (ActivityScreen) createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.api.ScreenIdentity.APP_DRAWER));
}
/**
* Return the lock screen, null if not created yet
*/
public ActivityScreen getLockScreen() {
return (HomeScreen) createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.engine.Screen.Identity.LOCK));
return (ActivityScreen) createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.api.ScreenIdentity.LOCK));
}
/**
* Return the floating screen, null if not created yet
*/
public Screen getFloatingScreen() {
return createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.engine.Screen.Identity.FLOATING));
return createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.api.ScreenIdentity.FLOATING));
}
/**
* Return the live wallpaper screen, null if not created yet
*/
public Screen getLiveWallpaperScreen() {
return createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.engine.Screen.Identity.LIVE_WALLPAPER));
return createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.api.ScreenIdentity.LIVE_WALLPAPER));
}
/**
* Return the background screen. This special screen is used when running background scripts. It can be used to query items and containers, but position and size may not be computed since the screen is not displayed and has no size.
*/
public Screen getBackgroundScreen() {
return createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.engine.Screen.Identity.BACKGROUND));
return createScreen(LLApp.get().getScreen(net.pierrox.lightning_launcher.api.ScreenIdentity.BACKGROUND));
}
/**
* @hide
*/
public Screen createScreen(net.pierrox.lightning_launcher.engine.Screen screen) {
if(screen.getIdentity() == net.pierrox.lightning_launcher.engine.Screen.Identity.HOME) {
if(screen == null){
return null;
} else if(screen.getIdentity() == ScreenIdentity.HOME) {
return new HomeScreen(this, screen);
} else if(screen.getContext() instanceof Activity) {
return new ActivityScreen(this, screen);
@ -349,21 +356,21 @@ public class Lightning {
}
/**
* Set a boolean variable. This is a shortcut for <code>LL.getVariables().edit().setBoolean(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
* Set a boolean variable. This is a shortcut for <code>getVariables().edit().setBoolean(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*/
public void setVariableBoolean(String name, boolean value) {
setVariable(name, value);
}
/**
* Set a boolean variable. This is a shortcut for <code>LL.getVariables().edit().setInteger(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
* Set a boolean variable. This is a shortcut for <code>getVariables().edit().setInteger(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*/
public void setVariableInteger(String name, long value) {
setVariable(name, (int)value);
}
/**
* Set a boolean variable. This is a shortcut for <code>LL.getVariables().edit().setFloat(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
* Set a boolean variable. This is a shortcut for <code>getVariables().edit().setFloat(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*/
public void setVariableFloat(String name, float value) {
if(Float.isNaN(value)) {
@ -373,7 +380,7 @@ public class Lightning {
}
/**
* Set a string variable. This is a shortcut for <code>LL.getVariables().edit().setString(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
* Set a string variable. This is a shortcut for <code>getVariables().edit().setString(name, value).commit();</code>. When modifying several at once, consider using the {@link net.pierrox.lightning_launcher.script.api.PropertyEditor} object instead for best efficiency.
*/
public void setVariableString(String name, String value) {
setVariable(name, value);
@ -570,7 +577,7 @@ public class Lightning {
context.sendBroadcast(intent);
throw pending;
} catch(IllegalStateException e) {
android.widget.Toast.makeText(context, "cannot wait for Tasker result in this context, set 'synchronous' to false", android.widget.Toast.LENGTH_SHORT).show();
Toast.makeText(context, "cannot wait for Tasker result in this context, set 'synchronous' to false", Toast.LENGTH_SHORT).show();
return false;
} finally {
org.mozilla.javascript.Context.exit();
@ -634,17 +641,27 @@ public class Lightning {
throw pending;
} catch (IllegalStateException e) {
// not called with continuation support
android.widget.Toast.makeText(context, "cannot display \"" + message + "\" in this context", android.widget.Toast.LENGTH_SHORT).show();
Toast.makeText(context, "cannot display \"" + message + "\" in this context", Toast.LENGTH_SHORT).show();
return false;
} finally {
org.mozilla.javascript.Context.exit();
}
} else {
android.widget.Toast.makeText(context, message, android.widget.Toast.LENGTH_SHORT).show();
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
return false;
}
}
/**
* Displays a toast (small message at the bottom of the screen).
* This is equivalent to <code>Toast.makeText(getEvent().getScreen().getContext(), text, Toast.LENGTH_LONG).show()</code>
* (you can use that code directly if you want a LENGTH_SHORT toast or to save the toast object instead of showing it).
* @param text message to display
*/
public void toast(String text){
Toast.makeText(getScriptScreen().getContext(), text, Toast.LENGTH_LONG).show();
}
/**
* Execute a function later.
* @param function need to be a function

View file

@ -7,6 +7,8 @@ import org.mozilla.javascript.Function;
/**
* Provides an access to the popup menu, so that it can be customized.
*
* An instance of this object can be retrieved by using directly the special variable 'menu' (which is the current Menu) when running a 'Menu' event.
*/
public class Menu {
/** Main item menu in edit mode */

View file

@ -2,6 +2,11 @@ package net.pierrox.lightning_launcher.script.api;
import net.pierrox.lightning_launcher.views.item.ItemView;
/**
* Represents a Page Indicator Item. No extra methods available.
*
* An instance of this object can be retrieved with any function that returns an {@link Item} when that returned item is a PageIndicator; or with {@link Container#addPageIndicator(float, float)}.
*/
public class PageIndicator extends Item {
/**
* @hide

View file

@ -5,6 +5,8 @@ import net.pierrox.lightning_launcher.views.item.ItemView;
/**
* The panel is a special kind of item, providing access to items contained in this panel.
*
* An instance of this object can be retrieved with any function that returns an {@link Item} when that returned item is a Panel; or with {@link Container#addPanel(float, float, float, float)}.
*/
public class Panel extends Item {

View file

@ -7,6 +7,11 @@ import net.pierrox.lightning_launcher.R;
import java.util.LinkedHashMap;
/**
* Enumeration class. Represents a Property object {@see PropertySet} {@see PropertyEditor}.
*
* An instance of this object can be created with {@link #getByName(String)}.
*/
public class Property {
public static final int TYPE_UNKNOWN = -1;
public static final int TYPE_BOOLEAN = 0;
@ -29,7 +34,9 @@ public class Property {
public static final String PROP_PAGE_BG_COLOR = "bgColor";
public static final String PROP_PAGE_STATUS_BAR_COLOR = "statusBarColor";
public static final String PROP_PAGE_STATUS_BAR_LIGHT = "statusBarLight";
public static final String PROP_PAGE_NAV_BAR_COLOR = "navigationBarColor";
public static final String PROP_PAGE_NAV_BAR_LIGHT = "navigationBarLight";
public static final String PROP_PAGE_SCROLLING_DIRECTION = "scrollingDirection";
// public static final String PROP_PAGE_ICON_PACK = "iconPack";

View file

@ -33,7 +33,7 @@ import java.util.HashMap;
/**
* Utility to modify one or more configuration settings at once. Modify one or more properties using the same PropertyEditor, then call {@link #commit()} to validate changes.
* This object is retrieved using {@link PropertySet#edit()}. You can chain calls this way:
* An instance of this object can be retrieved with {@link PropertySet#edit()}. You can chain calls this way:
* <pre><code>
* property_set.edit()
* .setInteger("someProperty", some_value)
@ -158,11 +158,21 @@ public class PropertyEditor {
for (Screen screen : LLApp.get().getScreens()) {
screen.onPageSystemBarsColorChanged(page);
}
} else if (key.equals(Property.PROP_PAGE_STATUS_BAR_LIGHT)) {
page_config.statusBarLight = (boolean) value;
for (Screen screen : LLApp.get().getScreens()) {
screen.onPageSystemBarsColorChanged(page);
}
} else if (key.equals(Property.PROP_PAGE_NAV_BAR_COLOR)) {
page_config.navigationBarColor = (int) value;
for (Screen screen : LLApp.get().getScreens()) {
screen.onPageSystemBarsColorChanged(page);
}
} else if (key.equals(Property.PROP_PAGE_NAV_BAR_LIGHT)) {
page_config.navigationBarLight = (boolean) value;
for (Screen screen : LLApp.get().getScreens()) {
screen.onPageSystemBarsColorChanged(page);
}
} else if (key.equals(Property.PROP_PAGE_SCROLLING_DIRECTION)) {
try {
page_config.scrollingDirection = PageConfig.ScrollingDirection.valueOf((String) value);

View file

@ -1,6 +1,6 @@
package net.pierrox.lightning_launcher.script.api;
import java.lang.reflect.Field;
import android.util.Pair;
import net.pierrox.lightning_launcher.configuration.FolderConfig;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
@ -8,14 +8,15 @@ import net.pierrox.lightning_launcher.configuration.ItemConfig;
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.data.*;
import net.pierrox.lightning_launcher.data.EventAction;
import net.pierrox.lightning_launcher.data.Page;
import android.util.Pair;
import java.lang.reflect.Field;
/**
* Access to container and item properties (aka settings).
* This object provides a way to query for configuration options as well as a mean to update them (see {@link #edit()}.
* Properties are accessed through their named. There are different property classes:
* This object provides a way to query for configuration options as well as a mean to update them (see {@link #edit()}).
* Properties are accessed through their name. There are different property classes:
* <ul>
* <li>container properties: options that can be seen in the desktop, folder and panel settings screen</li>
* <li>item properties: options available to all objects (such as box properties or pin mode)</li>
@ -30,6 +31,9 @@ import android.util.Pair;
* <li>Page Indicator: item, shortcut and page indicator properties</li>
* <li>Other objects: contains item properties only</li>
* </ul>
*
* An instance of this object can be retrieved with {@link Item#getProperties()}, {@link Container#getProperties()} or {@link Configuration#getProperties()}.
*
* The list of supported properties can be found below. Behavior when setting a value for a property marked as read only is unspecified and can lead to data loss.
* The same may appear when setting a value out of its bounds. These cases are currently not checked.
*
@ -64,7 +68,9 @@ import android.util.Pair;
* <tr><td><a href="/help/app/topic.php?id=57">bgColor</a></td><td>int</td><td>Read/Write</td><td>argb color</td></tr>
* <tr><td><a href="/help/app/topic.php?id=97">statusBarHide</a></td><td>boolean</td><td>Read/Write</td><td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=109">statusBarColor</a></td><td>int</td><td>Read/Write</td><td>argb color</td></tr>
* <tr><td><a href="/help/app/topic.php?id=513">statusBarLight</a></td><td>boolean</td><td>Read/Write</td><td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=138">navigationBarColor</a></td><td>int</td><td>Read/Write</td><td>argb color</td></tr>
* <tr><td><a href="/help/app/topic.php?id=514">navigationBarLight</a></td><td>boolean</td><td>Read/Write</td><td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=138">statusBarOverlap</a></td><td>boolean</td><td>Read/Write</td><td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=138">navigationBarOverlap</a></td><td>boolean</td><td>Read/Write</td><td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=96">screenOrientation</a></td><td>string</td><td>Read/Write</td><td>AUTO|PORTRAIT|LANDSCAPE|SYSTEM</td></tr>
@ -191,7 +197,8 @@ import android.util.Pair;
* <tr><td><a href="/help/app/topic.php?id=68">f.animationIn</a></td> <td>string</td> <td>Read/Write</td> <td>NONE|OPEN_CLOSE|SLIDE_FROM_LEFT|SLIDE_FROM_RIGHT|SLIDE_FROM_TOP|SLIDE_FROM_BOTTOM</td></tr>
* <tr><td><a href="/help/app/topic.php?id=69">f.animationOut</a></td> <td>string</td> <td>Read/Write</td> <td>NONE|OPEN_CLOSE|SLIDE_FROM_LEFT|SLIDE_FROM_RIGHT|SLIDE_FROM_TOP|SLIDE_FROM_BOTTOM</td></tr>
* <tr><td><a href="/help/app/topic.php?id=130">f.animFade</a></td> <td>boolean</td> <td>Read/Write</td> <td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=17">f.iconStyle</a></td> <td>string</td> <td>Read/Write</td> <td>NORMAL|GRID_2_2|STACK</td></tr>
* <tr><td><a href="/help/app/topic.php?id=17">f.iconStyle</a></td> <td>string</td> <td>Read/Write</td> <td>NORMAL|GRID_2_2|STACK|GRID_AUTO|GRID_3_3</td></tr>
* <tr><td><a href="/help/app/topic.php?id=515">f.outsideTapClose</a></td> <td>boolean</td> <td>Read/Write</td> <td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=93">f.autoClose</a></td> <td>boolean</td> <td>Read/Write</td> <td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=136">f.closeOther</a></td> <td>boolean</td> <td>Read/Write</td> <td>true/false</td></tr>
* <tr><td><a href="/help/app/topic.php?id=124">f.wAH</a></td> <td>string</td> <td>Read/Write</td> <td>LEFT|CENTER|RIGHT|CUSTOM</td></tr>
@ -287,7 +294,9 @@ public class PropertySet {
private Type mType;
/**
* @hide
*/
/*package*/ public PropertySet(Lightning lightning, Object script_object) {
mLightning = lightning;
mScriptObject = script_object;

View file

@ -2,7 +2,11 @@ package net.pierrox.lightning_launcher.script.api;
import android.graphics.Rect;
/** A rectangle class. */
/**
* A rectangle class in the format left-top-rigth-bottom.
*
* An instance of this object can be created with {@link #RectL(Rect)} or {@link #RectL(int, int, int, int)}; or retrieved with {@link Item#getCell()} or {@link Container#getBoundingBox()}.
*/
public class RectL {
private int l, t, r, b;
@ -13,6 +17,10 @@ public class RectL {
this.b = b;
}
/**
* Copy constructor. Creates a copy of the RectL
* @param r the rectL which will be copied.
*/
public RectL(android.graphics.Rect r) {
this(r.left, r.top, r.right, r.bottom);
}
@ -29,6 +37,10 @@ public class RectL {
return "["+l+","+t+","+r+","+b+"]";
}
/**
* Returns a java Rect with the same values.
* @return Java Rect object with the same values.
*/
public Rect toRect() {
return new Rect(l, t, r, b);
}

View file

@ -9,6 +9,8 @@ import java.util.HashMap;
/**
* This object is used to access script properties such as text, tag and menu attributes.
* Warning: this API is currently experimental.
*
* An instance of this object can be retrieved with {@link Lightning#getCurrentScript()}, {@link Lightning#getScriptByName(String)}, {@link Lightning#getScriptByPathAndName(String, String)}, {@link Lightning#getScriptById(String)}, {@link Lightning#createScript(String, String, String, int)} or {@link Lightning#getAllScriptMatching(int)}.
*/
public class Script {
public static final int FLAG_ALL = net.pierrox.lightning_launcher.script.Script.FLAG_ALL;
@ -93,7 +95,7 @@ public class Script {
* </pre></code>
* And then use it this way:
* <code><pre>
* eval(LL.getScript("some_script"));
* eval(getScriptByName("some_script").getText());
* doSomething();
* </pre></code>
*/

View file

@ -19,6 +19,8 @@ import java.io.File;
/**
* A shortcut is a label and an icon, tapping on it will usually launch an app.
* It is used for both so called 'apps' and 'shortcuts' because these two objects are really the same thing (technically)
*
* An instance of this object can be retrieved with any function that returns an {@link Item} when that returned item is a Shortcut; or with {@link Container#addShortcut(String, Intent, float, float)}.
*/
public class Shortcut extends Item {
@ -30,7 +32,7 @@ public class Shortcut extends Item {
}
/**
* Launch the intent associated with this shortcut. This generic method does nothing when the script is run in background: in this context an app or shortcut can be launched using LL.getContext().startActivity(item.getIntent)); instead.
* Launch the intent associated with this shortcut. This generic method does nothing when the script is run in background: in this context an app or shortcut can be launched using <code>getActiveScreen().getContext().startActivity(item.getIntent));</code> instead.
*/
public void launch() {
mItemView.getParentItemLayout().getScreen().launchItem(mItemView);

View file

@ -4,6 +4,8 @@ import net.pierrox.lightning_launcher.views.item.ItemView;
/**
* The StopPoint object allows getting and setting stop points values.
*
* An instance of this object can be retrieved with any function that returns an {@link Item} when that returned item is a StopPoint; or with {@link Container#addStopPoint(float, float)}.
*/
public class StopPoint extends Item {
/**

View file

@ -8,7 +8,7 @@ import java.util.ArrayList;
/**
* A VariableEditor is a tool to change the value of one or more variable.
* This object is retrieved using {@link VariableSet#edit()}. You can chain calls this way:
* An instance of this object can be retrieved with {@link VariableSet#edit()}. You can chain calls this way:
* <pre><code>
* variable_set.edit()
* .setInteger("someVariable", some_value)

View file

@ -1,12 +1,13 @@
package net.pierrox.lightning_launcher.script.api;
import net.pierrox.lightning_launcher.engine.variable.Value;
import net.pierrox.lightning_launcher.engine.variable.Variable;
import net.pierrox.lightning_launcher.engine.variable.VariableManager;
/**
* A VariableSet object enumerates known variables with their type and value.
* It is also the entry point to modify variable through
*
* An instance of this object can be retrieved with {@link Lightning#getVariables()}.
*/
public class VariableSet {

View file

@ -47,8 +47,7 @@ import java.util.List;
* These can be retrieved from the appropriate getter method.
*
* <p>
* Instances can be created with the synchronous factory methods {@link #generate(android.graphics.Bitmap)} and
* {@link #generate(android.graphics.Bitmap, int)}.
* An instance of this object can be created with {@link #generate(android.graphics.Bitmap)} or {@link #generate(android.graphics.Bitmap, int)}.
* <p>
* These should be called on a background thread, ideally the one in
* which you load your images on. Sometimes that is not possible, so asynchronous factory methods

View file

@ -15,6 +15,8 @@ import org.mozilla.javascript.Function;
/**
* A screen backed with an Android Activity.
*
* An instance of this object can be retrieved with any function that returns an {@link Screen} when that returned Screen is an ActivityScreen; or with {@link Lightning#getAppDrawerScreen()} or {@link Lightning#getLockScreen()}.
*/
public class ActivityScreen extends Screen {
/**

View file

@ -7,6 +7,8 @@ import net.pierrox.lightning_launcher.views.ItemLayout;
/**
* A specialized ActivityScreen used for the main home screen.
*
* An instance of this object can be retrieved with any function that returns an {@link ActivityScreen} when that returned ActivityScreen is a HomeScreen; or with {@link Lightning#getHomeScreen()}.
*/
public class HomeScreen extends ActivityScreen {
/**
@ -61,9 +63,37 @@ public class HomeScreen extends ActivityScreen {
* @param y absolute Y position, in pixel
* @param scale zoom factor (1=100%, 0.5=50%, negative values are acceptable, 0 is not very useful)
* @param animate whether to animate the move
* @see #goToDesktopPage(int, float, float, float, boolean) to use coordinates in page units
*/
public void goToDesktopPosition(int id, float x, float y, float scale, boolean animate) {
mScreen.goToDesktopPosition(id, -x * scale, -y * scale, scale, animate);
mScreen.goToDesktopPosition(id, -x * scale, -y * scale, scale, animate, true);
}
/**
* Go to a specified desktop and navigate to the specified page, with animation and a 1x scale. This method does nothing when the script is run in background.
* The benefit of using page coordinates is that it doesn't depend on the container geometry (screen orientation or resolution).
* @param id desktop identifier
* @param x horizontal page position
* @param y vertical page position
* @see #goToDesktopPosition(int, float, float) to use absolute coordinates
* @see #goToDesktopPage(int, float, float, float, boolean) to control scale and animation
*/
public void goToDesktopPage(int id, float x, float y) {
mScreen.goToDesktopPosition(id, -x, -y, 1, true, false);
}
/**
* Go to a specified desktop and navigate to the specified page. This method does nothing when the script is run in background.
* The benefit of using page coordinates is that it doesn't depend on the container geometry (screen orientation or resolution).
* @param id desktop identifier
* @param x horizontal page position
* @param y vertical page position
* @param scale zoom factor (1=100%, 0.5=50%, negative values are acceptable, 0 is not very useful)
* @param animate whether to animate the move
* @see #goToDesktopPosition(int, float, float) to use absolute coordinates
*/
public void goToDesktopPage(int id, float x, float y, float scale, boolean animate) {
mScreen.goToDesktopPosition(id, -x, -y, scale, animate, false);
}
}

View file

@ -25,6 +25,8 @@ import java.util.ArrayList;
* <li>the lock screen (see {@link ActivityScreen})</li>
* <li>the floating desktop</li>
* </ul>
*
* An instance of this object can be retrieved with {@link Event#getScreen()}, {@link Item#getScreen()}, {@link Lightning#getActiveScreen()}, {@link Lightning#getFloatingScreen()}, {@link Lightning#getLiveWallpaperScreen()}, {@link Lightning#getBackgroundScreen()}
*/
public class Screen {
private static final String EVENT_SOURCE_SCRIPT = "RUN_SCRIPT";
@ -272,7 +274,7 @@ public class Screen {
* Start an activity.
* Example:<code><pre>
* var intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.pierrox.net/")
* LL.startActivity(intent);</pre></code>
* getActiveScreen().startActivity(intent);</pre></code>
* @param intent intent to start the activity
* @return true if launch is successful, false if activity not found or permission denied
*/

View file

@ -5,14 +5,13 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Pair;
import net.pierrox.lightning_launcher.LLApp;
import net.pierrox.lightning_launcher.api.ScreenIdentity;
import net.pierrox.lightning_launcher.configuration.GlobalConfig;
import net.pierrox.lightning_launcher.data.LightningIntent;
import net.pierrox.lightning_launcher.engine.Screen;
import net.pierrox.lightning_launcher.script.Script;
import net.pierrox.lightning_launcher.engine.variable.Variable;
import net.pierrox.lightning_launcher.engine.variable.VariableManager;
import net.pierrox.lightning_launcher.script.Script;
import java.net.URISyntaxException;
@ -66,6 +65,6 @@ public class FireReceiver extends BroadcastReceiver {
private void runBackgroundScript(Integer id, String data) {
LLApp app = LLApp.get();
app.getAppEngine().getScriptExecutor().runScript(app.getScreen(Screen.Identity.BACKGROUND), id, "BACKGROUND", data);
app.getAppEngine().getScriptExecutor().runScript(app.getScreen(ScreenIdentity.BACKGROUND), id, "BACKGROUND", data);
}
}

View file

@ -29,9 +29,8 @@ public class ResourcesWrapper extends Resources {
Context translations_context = context.createPackageContext(pkg_name, 0);
mTranslationsResources = translations_context.getResources();
int initialCapacity = R.string.zzz - R.string.aaa + 10;
mStringTranslationMap = new SparseArray<>(initialCapacity);
mStringArrayTranslationMap = new SparseArray<>(initialCapacity);
mStringTranslationMap = new SparseArray<>(2000);
mStringArrayTranslationMap = new SparseArray<>(2000);
// this will be reached using the App context
sSharedInstance = this;

View file

@ -425,11 +425,6 @@ public class BoxLayout extends ViewGroup implements SharedAsyncGraphicsDrawable.
protected void dispatchDraw(Canvas canvas) {
sTmpRect.set(bl, bt, br, bb);
if(mAlpha!=255 && Build.VERSION.SDK_INT < 11) {
sTmpRectF.set(0, 0, getWidth(), getHeight());
canvas.saveLayerAlpha(sTmpRectF, mAlpha, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
}
if(mCurrentContentColor!=0) {
sContentPaint.setColor(mCurrentContentColor);
canvas.drawRect(sTmpRect, sContentPaint);
@ -458,7 +453,7 @@ public class BoxLayout extends ViewGroup implements SharedAsyncGraphicsDrawable.
}
if(mChildView != null) {
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.save();
canvas.clipRect(pl, pt, getWidth() - pr, getHeight() - pb);
canvas.translate(mChildLeft, mChildTop);

View file

@ -15,6 +15,7 @@ import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
@ -26,11 +27,22 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
public class FolderView extends BoxLayout {
public class FolderView extends FrameLayout {
public interface OnTapOutsideListener {
void onTapOutside(FolderView fv);
}
private static final int ANIM_DURATION=400;
private LinearLayout mContainer;
private FrameLayout mInnerContainer;
// the innermost container where the item layout is attached (no title, no border)
private FrameLayout mContentContainer;
// the container for title and content (without borders)
private LinearLayout mInnerContainer;
// the outer container adds borders around the inner container
private BoxLayout mOuterContainer;
private TextView mEmptyMsg;
private TextView mTitle;
private View mSeparator;
@ -50,35 +62,40 @@ public class FolderView extends BoxLayout {
private boolean mAllowEmptyMessage = true;
private OnTapOutsideListener mOnTapOutsideListener;
public FolderView(Context context) {
super(context, null, true);
super(context);
setVisibility(View.GONE);
mContainer=new LinearLayout(context);
mContainer.setOrientation(LinearLayout.VERTICAL);
mContainer.setGravity(Gravity.CENTER_HORIZONTAL);
mInnerContainer = new LinearLayout(context);
mInnerContainer.setOrientation(LinearLayout.VERTICAL);
mInnerContainer.setGravity(Gravity.CENTER_HORIZONTAL);
mInnerContainer=new FrameLayout(context);
mContentContainer = new FrameLayout(context);
mItemLayout=new ItemLayout(context, null);
mInnerContainer.addView(mItemLayout, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mContentContainer.addView(mItemLayout, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mEmptyMsg=new TextView(context);
mEmptyMsg.setGravity(Gravity.CENTER);
mEmptyMsg.setPadding(20, 20, 20, 20);
FrameLayout.LayoutParams elp=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
elp.gravity=Gravity.CENTER;
mInnerContainer.addView(mEmptyMsg, elp);
mContentContainer.addView(mEmptyMsg, elp);
mTitle=new MyTextView(context);
mTitle.setGravity(Gravity.CENTER);
mContainer.addView(mTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mInnerContainer.addView(mTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mSeparator=new View(context);
mSeparator.setBackgroundColor(0xffffffff);
mContainer.addView(mSeparator, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
mContainer.addView(mInnerContainer, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mInnerContainer.addView(mSeparator, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
mInnerContainer.addView(mContentContainer, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mOuterContainer = new BoxLayout(context, null, true);
addView(mOuterContainer, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
/**
@ -103,24 +120,12 @@ public class FolderView extends BoxLayout {
if(box.size[Box.MR]==0) box.size[Box.MR]=1;
if(box.size[Box.MB]==0) box.size[Box.MB]=1;
}
setChild(mContainer, box);
// if(mFolderConfig.borderStyle==FolderBorderStyle.PLAIN) {
// setPadding(mFolderConfig.borderPlainLeft, mFolderConfig.borderPlainTop, mFolderConfig.borderPlainRight, mFolderConfig.borderPlainBottom);
// setBackgroundColor(mFolderConfig.borderPlainColor);
// } else {
// if(mFolderConfig.animationGlitchFix) {
// // fix for an animation glitch that leaves some unrefreshed pixels sometime
// setPadding(1, 1, 1, 1);
// }
// }
mOuterContainer.setChild(mInnerContainer, box);
int visibility=mFolderConfig.titleVisibility ? View.VISIBLE : View.GONE;
mTitle.setVisibility(visibility);
mSeparator.setVisibility(visibility);
// mContainer.setBackgroundColor(mFolderConfig.fbackgroundColor);
// mContainer.setPadding(mFolderConfig.paddingLeft, mFolderConfig.paddingTop, mFolderConfig.paddingRight, mFolderConfig.paddingBottom);
if(mFolderConfig.titleVisibility) {
mTitle.setText(folder.getLabel());
mTitle.setTextSize(mFolderConfig.titleFontSize);
@ -149,6 +154,10 @@ public class FolderView extends BoxLayout {
}
}
public void setOnTapOutsideListener(OnTapOutsideListener onTapOutsideListener) {
mOnTapOutsideListener = onTapOutsideListener;
}
public void updateEmptyMessageVisibility() {
if(mPage.items.size()==0 && mAllowEmptyMessage) {
mEmptyMsg.setVisibility(View.VISIBLE);
@ -163,23 +172,25 @@ public class FolderView extends BoxLayout {
if(mEditMode) {
int[] offset=new int[2];
getLocationInWindow(offset);
mOuterContainer.getLocationInWindow(offset);
offset[0]-=container_offset[0];
offset[1]-=container_offset[1];
Matrix m=mItemLayout.getLocalTransform();
m.postTranslate(offset[0], offset[1]);
mItemLayout.setLocalTransform(m);
mOuterContainer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mContentContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mInnerContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mItemLayout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
} else {
if(mFolderConfig.autoFindOrigin) {
mItemLayout.setAutoFindOrigin(true);
}
mOuterContainer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mContentContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mInnerContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mItemLayout.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
@ -208,25 +219,27 @@ public class FolderView extends BoxLayout {
if(animate) {
Animation animation = getAnimation(false);
if(animation != null) {
startAnimation(animation);
mOuterContainer.startAnimation(animation);
return;
}
}
setVisibility(View.GONE);
}
@Override
public void resume() {
super.resume();
mOuterContainer.resume();
mItemLayout.resume();
}
@Override
public void pause() {
super.pause();
mOuterContainer.pause();
mItemLayout.pause();
}
public void destroy() {
mOuterContainer.destroy();
}
public Folder getOpener() {
return mOpener;
}
@ -277,7 +290,8 @@ public class FolderView extends BoxLayout {
}
lp.gravity = gravity;
setLayoutParams(lp);
mOuterContainer.setLayoutParams(lp);
requestLayout();
}
@ -288,12 +302,28 @@ public class FolderView extends BoxLayout {
if(mWaitingForLayoutToBeginAnimation) {
Animation animation = getAnimation(true);
if(animation != null) {
startAnimation(animation);
mOuterContainer.startAnimation(animation);
}
mWaitingForLayoutToBeginAnimation = false;
}
}
@Override
public void setOnLongClickListener(View.OnLongClickListener l) {
// redirect events on the real folder container
mOuterContainer.setOnLongClickListener(l);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(mFolderConfig.outsideTapClose && event.getAction() == MotionEvent.ACTION_DOWN) {
if(mOnTapOutsideListener != null) {
mOnTapOutsideListener.onTapOutside(this);
}
}
return false;
}
private Animation getAnimation(final boolean in) {
AnimationSet a=new AnimationSet(true);

View file

@ -1229,6 +1229,16 @@ public class ItemLayout extends ViewGroup {
computeCurrentLocalTransformValues();
}
public void goToPage(float x, float y, float to_scale, boolean animate) {
float to_x = (x * getWidth()) * to_scale;
float to_y = (y * getHeight()) * to_scale;
if(animate) {
animateZoomTo(to_x, to_y, to_scale);
} else {
moveTo(to_x, to_y, to_scale);
}
}
// recenter the view on the primary page after it has been scrolled multiple times in seamless mode
public void recenter() {
if(!mItemsBoundingBox.isEmpty()) { // this check does not apply if the ItemLayout has not been measured yet
@ -1991,7 +2001,7 @@ public class ItemLayout extends ViewGroup {
if(mEditMode && mVirtualEditBorders != null) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
canvas.scale(mVirtualEditBordersScale, mVirtualEditBordersScale);
canvas.translate(mVirtualEditBordersBounds.left, mVirtualEditBordersBounds.top);
mVirtualEditBorders.draw(canvas);
@ -2298,7 +2308,7 @@ public class ItemLayout extends ViewGroup {
} else {
Bitmap draggedBitmap = itemView.getDraggedBitmap();
if(draggedBitmap != null) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.save();
View sensibleView = itemView.getSensibleView();
float px = left + sensibleView.getLeft();
float py = top + sensibleView.getTop();

View file

@ -374,7 +374,7 @@ public abstract class ItemView extends TransformLayout implements TouchEventInte
final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(b);
float s = 1f / mDraggedBitmapScale;
int count = canvas.save(Canvas.MATRIX_SAVE_FLAG);
int count = canvas.save();
canvas.scale(s, s);
if(background != null) background.setAlpha(0); // ripples do not handle setVisible(false, false); (always restart)
view.draw(canvas);

View file

@ -142,7 +142,8 @@ public class PageIndicatorView extends ItemView {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int px = mMaxX - mMinX;
final int py = mMaxY - mMinY;
float radius = Math.max(mPageIndicator.dotsInnerRadius, mPageIndicator.dotsOuterRadius + mPageIndicator.dotsOuterStrokeWidth /2);
float stroke_width = mPageIndicator.dotsOuterStrokeWidth == 0 ? 1 : mPageIndicator.dotsOuterStrokeWidth;
float radius = Math.max(mPageIndicator.dotsInnerRadius, mPageIndicator.dotsOuterRadius + stroke_width);
int width = (int) Math.ceil((radius * 2) * px + mPageIndicator.dotsMarginX * (px>0 ? px-1 : 0));
int height = (int) Math.ceil((radius * 2) * py + mPageIndicator.dotsMarginY * (py>0 ? py-1 : 0));
setMeasuredDimension(width, height);
@ -161,7 +162,13 @@ public class PageIndicatorView extends ItemView {
return;
}
float radius = Math.max(mPageIndicator.dotsInnerRadius, mPageIndicator.dotsOuterRadius + mPageIndicator.dotsOuterStrokeWidth /2);
float stroke_width = mPageIndicator.dotsOuterStrokeWidth == 0 ? 1 : mPageIndicator.dotsOuterStrokeWidth;
// compute the anti aliasing delta : shift the drawing so that the outer circle is always perfectly aligned
float ad = (stroke_width % 2) == 0 ? 0 : 0.5f;
float radius = Math.max(mPageIndicator.dotsInnerRadius, mPageIndicator.dotsOuterRadius + stroke_width);
float scaled_cont_x = -(mContainerX-mContainerWidth/2)/mContainerScale;
float scaled_cont_y = -(mContainerY-mContainerHeight/2)/mContainerScale;
float pos_x_f = scaled_cont_x / mContainerWidth - 0.5f;
@ -172,7 +179,7 @@ public class PageIndicatorView extends ItemView {
for(int y=mMinY; y<mMaxY; y++) {
float cx = radius;
for(int x=mMinX; x<mMaxX; x++) {
canvas.drawCircle(cx, cy, mPageIndicator.dotsOuterRadius, mOuterCirclePaint);
canvas.drawCircle(cx+ad, cy+ad, mPageIndicator.dotsOuterRadius, mOuterCirclePaint);
if(x == mMinX && pos_x_f > mMaxX-1) {
pos_x_f = x - mMaxX + pos_x_f;
@ -189,7 +196,7 @@ public class PageIndicatorView extends ItemView {
if(dx>1) dx=1; dx = 1-dx;
if(dy>1) dy=1; dy = 1-dy;
mInnerCirclePaint.setAlpha((int) (255*dx*dy*max_alpha));
canvas.drawCircle(cx, cy, mPageIndicator.dotsInnerRadius, mInnerCirclePaint);
canvas.drawCircle(cx+ad, cy+ad, mPageIndicator.dotsInnerRadius, mInnerCirclePaint);
cx += radius*2 + mPageIndicator.dotsMarginX;
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppDark" parent="android:Theme.Material">
<item name="android:colorPrimary">@color/color_primary</item>
<item name="android:colorPrimaryDark">@color/color_primary_dark</item>
<item name="android:colorAccent">@color/color_accent</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<style name="AppLight" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:colorPrimary">@color/color_primary</item>
<item name="android:colorPrimaryDark">@color/color_primary_dark</item>
<item name="android:colorAccent">@color/color_accent</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">Lightning Launcher</string>
<string name="default_pack_name" translatable="false">English</string>
</resources>

View file

@ -102,7 +102,10 @@
<string name="app_killer_s">Kill apps with Lightning</string>
<string name="donate_t">Donate</string>
<string name="donate_s">Want to support Lightning?</string>
<string name="backup_t">Backup</string>
<string name="backup_t">Create a backup</string>
<string name="import_t">Load an external file</string>
<string name="import_e">Import failed!</string>
<string name="importing">Import in progress</string>
<string name="restore_t">Restore</string>
<string name="rate_t">Rate Lightning</string>
<string name="rate_s">Tell us what you think</string>
@ -293,6 +296,7 @@
<string name="no_diagonal_scrolling_t">Disable diagonal scrolling</string>
<string name="no_diagonal_scrolling_s">Only scroll in one direction at a time</string>
<string name="pinch_zoom_t">Pinch to zoom in or out</string>
<string name="otc_t">Tap outside to close</string>
<string name="auto_close_t">Auto close</string>
<string name="auto_close_s">Close the folder as soon as one of its app is launched</string>
<string name="anim_glitch_fix_t">Animation glitch fix</string>
@ -352,8 +356,10 @@
<string-array name="i_folder_e">
<item>Icon</item>
<item>Grid</item>
<item>Grid 2x2</item>
<item>Stack</item>
<item>Grid auto</item>
<item>Grid 3x3</item>
</string-array>
<string name="i_effect">Layers</string>
@ -633,7 +639,7 @@
<string name="tmpl_a_s">Load it from an installed APK</string>
<string name="tmpl_b_t">Browse existing templates</string>
<string name="tmpl_b_s">Get fresh new themes</string>
<string name="tmpl_e_t">Export template</string>
<string name="tmpl_e_t">Create a template</string>
<string name="tmpl_e_s">Long tap to read the tutorial</string>
<string name="tmpl_c">Select a template</string>
<string name="tmpl_e_m">Exporting…</string>
@ -836,7 +842,6 @@
<string name="tmpl_m">Merge: keep the current setup, import the template as new desktops</string>
<string name="tmpl_u">Update: keep desktops and items, apply style from desktops in the template only</string>
<string name="tmpl_b">Make a backup first</string>
<string name="apply_tmpl_m">You are about to apply the template \'%s\':</string>
<!-- added 171 -->
<string name="s_ls_lu_t">Launch unlock</string>
@ -926,7 +931,9 @@
<string name="sb_t">System bars</string>
<string name="sb_s">Set status and navigation bars visibility, transparency, etc.</string>
<string name="sbc_t">Status bar tint color</string>
<string name="sbl_t">Light status bar</string>
<string name="nbc_t">Navigation bar tint color</string>
<string name="nbl_t">Light navigation bar</string>
<string name="sb_c">Status bar</string>
<string name="nb_c">Navigation bar</string>
<string name="mi_app_store">Play Store</string>
@ -1217,6 +1224,7 @@
<string name="an_ohs">Open the hierarchy screen</string>
<string name="ov_pt">Setup</string>
<string name="ov_ps">The overlay desktop requires the permission to draw over other apps</string>
<string name="ov_r">The overlay desktop is enabled</string>
<string name="ism_t">Size mode</string>
<string-array name="ism_e">
<item>Standard</item>
@ -1305,149 +1313,13 @@
<string name="svgp_style">#%s style</string>
<string name="svgp_path">#%s path</string>
<string name="permission_label">Use Script Service</string>
<string name="permission_description">view, create, edit, delete and run scripts in Lightning Launcher</string>
<!-- deprecated: before 90 -->
<string-array name="d01"/>
<string name="d0"/>
<string name="d1"/>
<!-- deprecated: 90 -->
<string name="color_t"/>
<string name="color_s"/>
<string name="wp_c"/>
<string name="wp_t"/>
<string name="wp_select_t"/>
<string name="wp_select_s"/>
<string name="wp_tint_color_t"/>
<string name="wp_tint_color_s"/>
<string name="wp_soft_t"/>
<string name="wp_soft_s"/>
<!-- deprecated: 92 -->
<string name="theme_label_classic"/>
<string name="theme_label_compact"/>
<string name="theme_label_list_icons"/>
<string name="theme_label_list_labels"/>
<string name="theme_label_icons_only"/>
<!-- deprecated: 93 -->
<string name="app_not_installed"/>
<!-- deprecated: 95 -->
<string name="app_screen_switcher_t"/>
<string name="app_screen_switcher_s"/>
<!-- deprecated: 103 -->
<string-array name="action_names">
<item>Do nothing (lock)</item>
<item>Launch the App Drawer</item>
<item>Zoom full scale</item>
<item>Zoom 100p.</item>
<item>Zoom toggle full scale/100p.</item>
<item>Previous desktop</item>
<item>Next desktop</item>
<item>Edit layout</item>
<item>Add object</item>
<item>Customize Lightning</item>
<item>Customize current desktop or folder</item>
<item>Launch app</item>
<item>Launch shortcut</item>
<item>Select wallpaper</item>
<item>Launcher menu</item>
<item>Show/hide status bar</item>
<item>Show/hide app menu &amp; status bar</item>
<item>Show notifications</item>
<item>Search</item>
<item>Move item</item>
<item>Customize item</item>
<item>Item menu</item>
<item>Launch item</item>
</string-array>
<!-- deprecated: 114 -->
<string name="auto_stop_t">Use auto scroll stops</string>
<string name="auto_stop_s">Automatically stop scrolling at desktop edges</string>
<!-- deprecated: 116 -->
<string name="select_backup">Select a backup archive to restore</string>
<!-- deprecated: 119 -->
<string-array name="anim_e">
<item>None</item>
<item>Open / Close</item>
<item>Fade in/out</item>
</string-array>
<!-- deprecated: 124 -->
<string name="mi_reset">Reset scale/rotate</string>
<!-- deprecated: 125 -->
<string name="gc_sfde">Single finger scroll in edit mode</string>
<!-- deprecated: 135 -->
<string name="grid_pl">Toggle portrait/landscape</string>
<!-- deprecated: 144 -->
<string name="scroll_speed_t">Scrolling speed</string>
<!-- deprecated: 170 -->
<string name="apply_tmpl_p">Backup then apply</string>
<string name="apply_tmpl_n">Only apply</string>
<!-- deprecated: 191 -->
<string name="pick_default">Default icon</string>
<!-- deprecated: 208 -->
<string name="bo_t">Transparent bars and content overlap</string>
<string name="ad_ab_c_s">Background image, visibility</string>
<!-- deprecated: 221 -->
<string name="wrap_t">Seamless mode</string>
<!-- deprecated: beyond -->
<string name="ip_blank">Blank image</string>
<string name="min_ram_t">Minimize memory usage</string>
<string name="min_ram_s">Lightning will use less RAM, but might slow down a bit. Requires restart</string>
<string name="mi_es_show_hidden">Show hidden</string>
<string name="mi_es_hide_hidden">Hide hidden</string>
<string name="mi_zorder">Move forwards/backwards</string>
<string name="snap_t">Snapping</string>
<string-array name="snap_e">
<item>None</item>
<item>Center</item>
<item>Edge</item>
<item>Center &amp; Edge</item>
</string-array>
<string name="copy_style_toast">Tap an item to copy its style</string>
<string name="copy_style_cancel">Style copy canceled</string>
<string name="copy_style_done">Style has been copied.</string>
<string name="mi_edit_copy_style">Copy a style</string>
<string name="mi_app">App…</string>
<string name="mi_fo">Folder settings</string>
<string name="items_t">Items</string>
<string name="items_s">Fonts, colors, icons, box settings, and more</string>
<string name="mi_es_add_folder">Add folder</string>
<string name="mi_es_add_pi">Add page indicator</string>
<string name="gc_hpie_s">Long tap for the description</string>
<string name="tut_basic_editing">First steps</string>
<string name="hide_statusbar_s">Hit menu to show it</string>
<string name="mph"></string>
<string name="tr_ut">About Lightning</string>
<string name="tr_um">You are a long time user of the free version of Lighting Launcher, thank you.\n\nAlthough this version has been replaced with a trial version, you will still benefit from all previously existing features for free, as well as most improvements made in the full app since the last update.\n\nIf you wish to support this app, please consider purchasing the unlock key at a discounted loyalty price.\n\nThanks!</string>
<string name="ip_bic">Broken icon pack</string>
<string name="sp_none">No script</string>
<string name="mi_pick_sh">Select shortcut</string>
<!-- Do not translate -->
<string name="app_name">Lightning Launcher</string>
<string name="default_pack_name">English</string>
<!-- Do not change -->
<string name="aaa" />
<string name="zzz" />
<string-array name="aaa1" />
<string-array name="zzz1" />
<string name="sc_disable_toast">Script disabled. Open it in the editor to enable again</string>
<string name="srch_ttl">Search text</string>
<string name="srch_back">Backwards</string>
<string name="srch_regexp">Regexp</string>
<string name="srch_case">Match case</string>
<string name="sc_ind">Autoindentation</string>
</resources>

View file

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

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