Skip to content

Instantly share code, notes, and snippets.

@TrianguloY
Last active July 14, 2026 05:21
Show Gist options
  • Select an option

  • Save TrianguloY/99978849e28c33c302dc6c499241d15d to your computer and use it in GitHub Desktop.

Select an option

Save TrianguloY/99978849e28c33c302dc6c499241d15d to your computer and use it in GitHub Desktop.
Lightning Launcher script collection

These are all the scripts that I still keep on my phone for Lightning launcher (the best Android launcher ever).

If you have never heard or used this launcher, these will be useless.

If you have, and you remember me, these may look fun to check and see what crazy shenanigans I never published on the wiki.

In any case I decided to post them here for preservation. I had very little experience, I apologize for the 'unusual' style of programming.

They are unedited, shown here without any modification, they may or may not work wihout minimal tweaks.

A bit of context:

  • things with prefix '[]' are those I was working on. those '[!]' were almost ready to be published.
  • '[personal]' are own scripts for my own desktops.
  • '[wiki]' are mostly published on the wiki but kept because I used them
  • '[tool]' are useful things for different reasons.
  • other elements are what they represent, probably.

You are free to use them however you want. My only requirement is that you mention that you got it from here, and that I was the original author. Also, if for some reason you do use them, please tell me! I would like to know!

//Flags: app
//Name: 8 weel
/* About the script
* Purpose : Make all items in a container animate on a figure 8 when scrolling left and right
* Author : TBog
* Link: www.google.com/+BogdanTautuTBog
*/gete
// v0.1
function empty( mixedVar )
{
/*discuss at: http://locutus.io/php/empty/ */
var undef, key, i, len;
var emptyValues = [undef, null, false, 0, '', '0'];
for ( i = 0, len = emptyValues.length; i < len; i++ )
{
if ( mixedVar === emptyValues[i] )
{
return true;
}
}
if ( typeof mixedVar === 'object' )
{
for ( key in mixedVar )
{
if ( Object.hasOwnProperty.call(mixedVar, key) )
{
return false;
}
}
return true;
}
return false;
}
function getWheelItems( container )
{
var items = container.getAllItems();
var a = [];
var na = 0;
for ( var i = items.length - 1; i >= 0; i -= 1 )
{
var item = items[i];
var type = item.getType();
// we are only interested in shortcuts and folders
if ( type != 'Shortcut' && type != 'Folder' )
{
continue;
}
// var prop = item.getProperties();
// var pinMode = prop.getString( 'i.pinMode' );
// /*NONE|XY|X|Y*/
// if ( pinMode.indexOf( 'X' ) == -1 )
// {
// prop.edit().setString( 'i.pinMode', 'X' ).commit();
// }
// var onGrid = prop.getBoolean( 'i.onGrid' );
// if ( onGrid )
// {
// prop.edit().setBoolean( 'i.onGrid', false ).commit();
// }
a[na++] = item;
}
return a;
}
function isConfigItemName( name )
{
if ( empty(name) )
return false;
if ( name.indexOf( '8w_config' ) != -1 )
return true;
if ( name.indexOf( '8w_setup' ) != -1 )
return true;
return false;
}
function getConfigItems( container )
{
var items = container.getAllItems();
var arrConfigItems = [];
for ( var i = 0; i < items.length; i += 1 )
{
var name = items[i].getName();
if ( isConfigItemName(name) )
{
arrConfigItems.push( items[i] );
}
}
return arrConfigItems;
}
function filterConfigItems( items )
{
for ( var i = 0; i < items.length; i += 1 )
{
var name = items[i].getName();
if ( isConfigItemName(name) )
{
// remove from list
items.splice( i--, 1 );
}
}
return items;
}
function cubicBezier( p0, p1, p2, p3, t )
{
return ( 1 - t ) * ( 1 - t ) * ( 1 - t ) * p0 + 3 * ( 1 - t ) * ( 1 - t ) * t * p1 + 3 * ( 1 - t ) * t * t * p2 + t * t * t * p3;
}
function scaleAnim( t )
{
return cubicBezier( 1, 0, 1, 0, t );
}
function showConfigMenu( container )
{
bindClass( 'android.app.AlertDialog' );
bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceListView' );
bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceCheckBox' );
var ctx = getActiveScreen().getContext();
var prefColorize = new LLPreferenceCheckBox( 0, 'Colorize', 'desaturate items', true, null );
var listView = new LLPreferenceListView( ctx, null );
listView.setPreferences( [prefColorize] );
var builder = new AlertDialog.Builder( ctx );
builder.setView( listView );
builder.setTitle( '8wheel settings' );
builder.setPositiveButton( 'Save',
{
onClick: function( dialog, id )
{
dialog.dismiss();
}
} );
builder.setNegativeButton( 'Cancel', null );
builder.show();
}
function createScriptShortcut( container )
{
var scriptId = getCurrentScript().getId();
var intent = Intent.parseUri("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.Dashboard;i.a=35;S.d="+scriptId+";end",0);
if ( empty(intent) )
return false;
return container.addShortcut('8wheel', intent, 0, 0);
}
function showSetupMenu( container )
{
bindClass( 'android.app.AlertDialog' );
bindClass( 'android.content.DialogInterface' );
bindClass( 'android.text.Html' );
bindClass( 'android.view.View' );
bindClass( 'android.view.ContextThemeWrapper' );
bindClass( 'android.widget.ListView' );
bindClass( 'android.widget.LinearLayout' );
bindClass( 'android.widget.ScrollView' );
bindClass( 'android.widget.TextView' );
bindClass( 'android.widget.Button' );
bindClass( 'android.R' );
var ctx = getActiveScreen().getContext();
var builder = new AlertDialog.Builder( ctx, R.style.Theme_Material_Dialog );
var ctxTheme = new ContextThemeWrapper( ctx, R.style.Theme_Material_Dialog );
var rootView = new ScrollView( ctxTheme );
var linearView = new LinearLayout( ctxTheme );
linearView.setOrientation( LinearLayout.VERTICAL );
linearView.setShowDividers( LinearLayout.SHOW_DIVIDER_MIDDLE );
linearView.setDividerDrawable( ctx.getResources().getDrawable(R.drawable.divider_horizontal_textfield) );
var textView = new TextView( ctxTheme );
textView.setText( "Do not edit the container after the 8wheel is setup; use this dialog to stop the script first" );
linearView.addView( textView );
var btn = new Button( ctxTheme );
btn.setAllCaps( false );
var hex = Number(container.getId()).toString(16);
hex = "000000".substr(0, 6 - hex.length) + hex;
btn.setText( 'Setup 8wheel in container #' + hex );
btn.setOnClickListener( new View.OnClickListener()
{
onClick: function( view )
{
var html = [];
var a = getWheelItems( container );
var na = a.length;
html.push(
'Found <b>', na, '</b> items'
);
a = filterConfigItems( a );
var nConfigItems = 0;
if ( a.length != na )
{
nConfigItems = na - a.length;
html.push(
'<br>',
'Found <b>', nConfigItems, '</b> config items'
);
na = a.length;
}
if ( na < 5 )
{
alert('Only found ' + na + ' item(s).\nAdd more shortcuts and/or folders and try again.');
return;
}
var nPinned = 0;
var nDetached = 0;
for ( var i = 0; i < na; i+= 1 )
{
var prop = a[i].getProperties();
var pinMode = prop.getString( 'i.pinMode' );
/*NONE|XY|X|Y*/
if ( pinMode.indexOf( 'X' ) == -1 )
{
prop.edit().setString( 'i.pinMode', 'X' ).commit();
nPinned+= 1;
}
var onGrid = prop.getBoolean( 'i.onGrid' );
if ( onGrid )
{
prop.edit().setBoolean( 'i.onGrid', false ).commit();
nDetached+= 1;
}
}
html.push(
'<br>',
'Pinned <b>', nPinned, '</b> items',
'<br>',
'Detached from grid <b>', nDetached, '</b> items'
);
var itemConfig, itemSetup;
var aCfgBtns = getConfigItems( container );
for ( var i = 0; i < aCfgBtns.length; i+= 1 )
{
switch( aCfgBtns[i].getName() )
{
case '8w_config':
itemConfig = aCfgBtns[i];
break;
case '8w_setup':
itemSetup = aCfgBtns[i];
break;
}
}
// the lists become invalid after we create new items
aCfgBtns = [];
a = [];
na = 0;
if ( empty(itemConfig) )
{
var item = createScriptShortcut( container );
if ( empty(item) )
{
html.push(
'<br>',
'<b>8wheel config</b> button not found and can\'t be created'
);
}
else
{
item.setName('8w_config');
item.getProperties().edit()
.setString('s.label', '<b>8wheel</b> config')
.setString( 'i.pinMode', 'X' )
.setBoolean( 'i.onGrid', false )
.commit();
item.setPosition(0, container.getHeight() - item.getHeight());
html.push(
'<br>',
'<b>8wheel config</b> button created'
);
}
}
else
{
html.push(
'<br>',
'<b>8wheel config</b> button found'
);
}
if ( empty(itemSetup) )
{
var item = createScriptShortcut( container );
if ( empty(item) )
{
html.push(
'<br>',
'<b>8wheel setup</b> button not found and can\'t be created'
);
}
else
{
item.setName('8w_setup');
item.getProperties().edit()
.setString('s.label', '<b>8wheel</b> setup')
.setString( 'i.pinMode', 'X' )
.setBoolean( 'i.onGrid', false )
.commit();
item.setPosition(container.getWidth() - item.getWidth(), container.getHeight() - item.getHeight());
html.push(
'<br>',
'<b>8wheel setup</b> button created'
);
}
}
else
{
html.push(
'<br>',
'<b>8wheel setup</b> button found'
);
}
var containerPropEditor = container.getProperties().edit();
containerPropEditor.setEventHandler('posChanged', EventHandler.RUN_SCRIPT, getCurrentScript().getId());
containerPropEditor.commit();
save();
var label = new TextView( ctxTheme );
label.setText( Html.fromHtml(html.join('')) );
view.getParent().addView(label, view.getParent().indexOfChild(view) + 1);
}
} );
linearView.addView( btn );
btn = new Button( ctxTheme );
btn.setAllCaps( false );
btn.setText( 'Stop 8wheel in container #' + hex );
btn.setOnClickListener( new View.OnClickListener()
{
onClick: function( view )
{
var aCfgBtns = getConfigItems( container );
for ( var i = 0; i < aCfgBtns.length; i+= 1 )
{
container.removeItem( aCfgBtns[i] );
}
container.getProperties().edit()
.setEventHandler('posChanged', EventHandler.NOTHING, '')
.setBoolean( 'rearrangeItems', false )
.commit();
var a = getWheelItems( container );
for ( var i = 0; i < a.length; i+= 1 )
{
try {
a[i].setScale( 1, 1 );
} catch (Exception)
{
// ignore
}
a[i].setVisibility( true );
a[i].getProperties().edit()
.setInteger( 'i.alpha', 0xff )
.setInteger( 's.iconColorFilter', 0xFFffffff )
.setInteger( 's.labelFontColor', 0xFFffffff )
.setString( 'i.pinMode', 'NONE' )
.setBoolean( 'i.onGrid', true )
.commit();
a[i].setCell(i, 0, i + 1, 1);
}
save();
}
} );
linearView.addView( btn );
var linearViewShowHideShortcuts = new LinearLayout( ctxTheme );
linearViewShowHideShortcuts.setOrientation( LinearLayout.VERTICAL );
var linearViewHorizontal = new LinearLayout( ctxTheme );
linearViewHorizontal.setOrientation( LinearLayout.HORIZONTAL );
textView = new TextView( ctxTheme );
textView.setText( Html.fromHtml('Configure <b>Setup</b> and <b>Config</b> shortcuts') );
linearViewShowHideShortcuts.addView( textView );
btn = new Button( ctxTheme );
btn.setAllCaps( false );
btn.setText( 'Show' );
btn.setOnClickListener( new View.OnClickListener()
{
onClick: function( view )
{
var txt = view.getText().toString().split("\n", 1);
var items = getConfigItems( container );
for ( var i = 0; i < items.length; i+= 1 )
{
var item = items[i];
item.setVisibility( true );
}
Android.makeNewToast( Html.fromHtml('<b>Setup</b> and <b>Config</b> shortcuts are now visible'), true ).show();
}
} );
linearViewHorizontal.addView( btn );
btn = new Button( ctxTheme );
btn.setAllCaps( false );
btn.setText( 'Hide' );
btn.setOnClickListener( new View.OnClickListener()
{
onClick: function( view )
{
var txt = view.getText().toString().split("\n", 1);
var items = getConfigItems( container );
for ( var i = 0; i < items.length; i+= 1 )
{
var item = items[i];
item.setVisibility( false );
}
Android.makeNewToast( Html.fromHtml('<b>Setup</b> and <b>Config</b> shortcuts are now hidden'), true ).show();
}
} );
linearViewHorizontal.addView( btn );
linearViewShowHideShortcuts.addView( linearViewHorizontal );
linearView.addView( linearViewShowHideShortcuts );
rootView.addView( linearView );
builder.setView( rootView );
builder.setCancelable( true );
builder.setTitle( '8wheel setup' );
builder.setNeutralButton( 'Close',
{
onClick: function( dialog, id )
{
dialog.dismiss();
}
} );
var dialog = builder.create();
dialog.setOnShowListener( new DialogInterface.OnShowListener()
{
onShow:function()
{
rootView.scrollTo(0,0);
}
} );
dialog.show();
}
function updatePosition(container, offsetScroll)
{
var a = getWheelItems( container );
a = filterConfigItems( a );
var na = a.length;
var x, y, pos, scale;
var w2 = container.getWidth() / 2;
var h2 = container.getHeight() / 2;
var radius = Math.min( w2, h2 ) * 0.5;
var sizeRef = radius;
for ( var i = 0; i < na; i += 1 )
{
pos = i / na + offsetScroll;
/* compute modulo 1 */
pos = pos - Math.floor( pos );
scale = 0;
if ( pos <= 0.5 )
{
scale += pos * 2;
/*make scale 0..1*/
var p = pos * 2;
x = Math.cos( Math.PI * 2 * p - Math.PI / 2 ) * radius;
y = Math.sin( Math.PI * 2 * p - Math.PI / 2 ) * radius + radius;
}
else
{
scale += ( 1 - pos ) * 2;
/*make scale 1..0*/
var p = ( pos - 0.5 ) * -2;
x = Math.cos( Math.PI * 2 * p + Math.PI / 2 ) * radius;
y = Math.sin( Math.PI * 2 * p + Math.PI / 2 ) * radius - radius;
}
scale = scaleAnim( scale );
var alpha = scale < fadeEnd ? 0 : ( scale < fadeStart ? ( ( scale - fadeEnd ) / ( fadeStart - fadeEnd ) ) : 1 );
var colorize = scale < colorizeEnd ? colorizeEndValue : ( scale < colorizeStart ? ( ( scale - colorizeEnd ) / ( colorizeStart - colorizeEnd ) * ( colorizeStartValue - colorizeEndValue ) + colorizeEndValue ) : colorizeStartValue );
colorize = Math.round( colorize * 255 ) << 24;
var labelColor = colorize | 0xffffff;
/*var shadowColor = colorize|0xff000000;*/
colorize = colorize | 0xffffff;
alpha = Math.round( alpha * 255 );
a[i].setVisibility( alpha > 0 );
a[i].getProperties().edit().setInteger( 'i.alpha', alpha ).setInteger( 's.iconColorFilter', colorize ).setInteger( 's.labelFontColor', labelColor ) /*.setInteger('s.labelShadowColor',shadowColor)*/
.commit();
scale *= 1.5;
x += w2;
y += h2;
try {
a[i].setScale( scale, scale );
} catch (e)
{
// probably edit mode
return;
}
x -= a[i].getWidth() / 2 * scale;
y -= a[i].getHeight() / 2 * scale;
a[i].setPosition( x, y );
}
}
/*Start of config area (Default values)*/
var fadeStart = 0.47;
var fadeEnd = 0.35;
var colorizeStart = 0.9;
var colorizeStartValue = 1;
var colorizeEnd = 0.7;
var colorizeEndValue = 0.1;
/*End of config area*/
var event = getEvent();
switch ( event.getSource() )
{
case 'MENU_APP':
showSetupMenu( event.getContainer() );
return;
case 'I_CLICK':
case 'SHORTCUT':
{
var btn = event.getItem();
switch ( btn.getName() )
{
case '8w_config':
showConfigMenu( btn.getParent() );
return;
case '8w_setup':
showSetupMenu( btn.getParent() );
}
return;
}
case 'C_POSITION_CHANGED':
{
var container = event.getContainer();
var offsetScroll = container.getPositionX() / container.getWidth() * 0.5;
updatePosition(container, offsetScroll);
return;
}
default:
alert( 'unknown event source ' + event.getSource() );
return;
}
if ( empty( container.getTag("8wheel") ) )
{
/* alert('Add shortcuts and/or folders to this container then enable the script');
getCurrentScript().setFlag(Script.FLAG_DISABLED, true);
return;
*/
;
}
//Flags:
//Name: [!] barrier scrolling
var NAME="barrier";
var cont = LL.getEvent().getContainer();
var script=LL.getCurrentScript();
//container rect
var contrect=[cont.getPositionX(),cont.getPositionY(),cont.getPositionX()+cont.getWidth()/cont.getPositionScale(),cont.getPositionY()+cont.getHeight()/cont.getPositionScale()];
//barriers
var barriers=[];
var items=cont.getItems();
for(var t=0;t<items.getLength();++t){
var item=items.getAt(t);
if(item.getLabel()==NAME) barriers.push([item.getPositionX(),item.getPositionY(),item.getPositionX()+item.getWidth(),item.getPositionY()+item.getHeight()]);
}
//check if collide
if(collide(contrect,barriers)){
var prev=script.getTag();
if(prev!=null){
prev=prev.split(" ");
cont.setPosition(prev[0],prev[1],prev[2],false);
cont.cancelFling();
}
}else{
script.setTag([cont.getPositionX(),cont.getPositionY(),cont.getPositionScale()].join(" "));
}
function collide(a,bList){
for(var t=0;t<bList.length;++t){
var b=bList[t];
if( a[0]>=b[2] || a[1]>=b[3] || b[0]>=a[2] || b[1]>=a[3] ) continue;
return true;
}
return false;
}
//Flags: app item custom
//Name: [!] binding dictionary
var directory = "LightningLauncher/binding_dictionary";
//classes
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface");
LL.bindClass("java.io.File");
LL.bindClass("java.io.FileWriter");
LL.bindClass("android.os.Environment");
LL.bindClass("java.io.BufferedReader");
LL.bindClass("java.io.FileReader");
//vars
var MAX = 50;
var item = LL.getEvent().getItem();
var script = LL.getCurrentScript();
var saved;
var properties;
var folder = new File(Environment.getExternalStorageDirectory()+"/"+directory);
folder.mkdirs();
//start
loadSaved();
main();
/// menu ///
function main(){
var entries = ["-- Add binding to the dictionary... --\n"]
.concat(saved.names
.map(function(v,i,a){
return v+"\n{"+cut(saved.formulas[i])+"}\n";
}));
list(entries
,f_main
,null
,"Binding dictionary, choose");
}
//gets the chosen entry on the main menu
function f_main(which){
if(which==0)
toDictionary();
else
main2(which-1);
}
//what to do with the binding selected
function main2(data){
list(["Add to the item...","See/Edit/delete binding...","Rename binding..."]
,f_main2
,main
,"Choose what to do with the binding"
,data);
}
//gets the chosen option in the main2 menu
function f_main2(which,data){
if(which==0)
toItem(data);
else if(which==1)
editor(data);
else if(which==2)
rename(data);
}
/// add to item ///
//shows the list of properties to choose
function toItem(data){
if(item==null){
noItemAlert()
main()
return;
}
list(properties
,f_toItem
,main2
,"Choose the property where to set the binding"
,data);
}
//gets the chosen property
//adds the binding to the item
function f_toItem(which,data){
var target=Property[properties[which]];
var binding=saved.formulas[data];
//alert(item+"\n"+binding+"\n"+target);
var old=item.getBindingByTarget(target);
if(old!=null
&& !confirm("There is already a binding on that property, do you want to override it?\n Current binding:\n"+old.getFormula())){
toItem(data);
return;
}
if(confirm("Confirm the data:\nTarget:"+target+"\nBinding:"+ binding)){
item.setBinding(target, binding,true);
Android.makeNewToast("Binding set",true).show()
main();
}else{
toItem(data);
}
}
/// add to dictionary ///
//shows the list of sources to choose
function toDictionary(){
list(["From text...","From item...","From launcher..."]
,f_toDictionary
,main
,"Choose from where to take it");
}
//gets the source chosen
function f_toDictionary(which){
if(which==0)
textToDictionary();
else if(which==1)
itemToDictionary();
else if(which==2)
fromLauncher();
}
//prompts the user to enter a name and formula to save
function textToDictionary(){
var formula="";
var name="";
while(true){
formula = prompt("Enter the formula of the binding",formula);
if(formula==null){
toDictionary();
return;
}
name = prompt("Enter the name of the binding",name||"");
if(name!=null
&& addToDictionary(name,formula)){
toDictionary();
return;
}
}//end while
}
//shows the list of bindings of the item to choose
function itemToDictionary(){
if(item==null){
noItemAlert();
toDictionary();
return;
}
var rawBindings = item.getAllBindings();
var names = [];
var itemBindings=[];
for(var t=0;t<rawBindings.getLength();++t){
var form=rawBindings.getAt(t).getFormula();
names.push(rawBindings.getAt(t).getTarget()+"{"+cut(form)+"}");
itemBindings.push(form);
}
if(names.length==0){
alert("The selected item has no bindings");
toDictionary();
return;
}
list(names
,f_itemToDictionary
,toDictionary
,"Choose the binding to save into the dictionary"
,itemBindings);
}
//gets which binding to add
function f_itemToDictionary(which,itemBindings){
var formula = itemBindings[which];
var name = "";
while(true){
name = prompt("Enter the name of the binding",name);
if(name==null){
itemToDictionary();
return;
}
if(addToDictionary(name,formula)){
itemToDictionary();
return;
}
}//end while
}
/// editor ///
function editor(index){
var output=saved.formulas[index];
while(true){
output=prompt(saved.names[index]+" (save an empty string to delete)",output);
if(output==null){
main2(index);
return;
}else if(output==""){
if(deleteBinding(index)){
main();
return;
}
}else if(output!=saved.formulas[index]){
if(updateBinding(index,output)){
main2(index);
return
}
}else{
main2(index);
return;
}
}//end while
}
/// rename ///
function rename(index){
var name = saved.names[index];
while(true){
name = prompt("New name:",name);
if(name==null){
main2(index);
return;
}else if(name==""){
if(deleteBinding(index)){
main();
return;
}
}else if(name!=saved.names[index]){
if(renameBinding(index,name)){
main2(index);
return;
}
}else{
main2(index);
return;
}
}//end while
}
/// import from launcher ///
var ids;
function fromLauncher(){
if(!confirm("This will search all bindings from all items in all desktops + the app drawer and ask to save them in the dictionary.\nBindings already in the dictionary will be skipped.\nYou will be asked one by one\n\n Start the process?")){
toDictionary();
return;
}
ids=[];//ids of containers, to avoid recursion
var desktops=LL.getAllDesktops();
for(var t=0;t<desktops.getLength();++t){
importFrom(LL.getContainerById(desktops.getAt(t)));
}
importFrom(LL.getContainerById(99));
Android.makeNewToast("Done importing", true).show();
toDictionary();
}
function importFrom(c){
if(ids.indexOf(c.getId())!=-1) return;
ids.push(c.getId());
var items=c.getItems();
for(var t=0;t<items.getLength();++t){
var item = items.getAt(t);
var bindings = item.getAllBindings();
for(var j=0;j<bindings.getLength();++j){
var bind=bindings.getAt(j);
var formula=bind.getFormula();
if(saved.formulas.indexOf(formula)!=-1) continue;
addToDictionary(item.getId()+"-"+bind.getTarget(),formula);
}
if(item.getType()=="Panel" || item.getType()=="Folder")
importFrom(item.getContainer());
}
}
/// global ///
//@return true if saved, false if not
function addToDictionary(name,formula){
if(name==null||name==""){
alert("Error: You can't use an empty name");
return false;
}
if(formula==null||formula==""){
alert("Error: You can't use an empty formula");
return false;
}
name=name.replace(/[^a-zA-Z0-9 _.-]/g, "_");
var indexformula = saved.formulas.indexOf(formula);
var indexname = saved.names.indexOf(name);
if(indexname!=-1){
if(indexformula==indexname){
Android.makeNewToast("Already in the dictionary", true).show();
return true;
}
alert("There is already a binding with this name ("+name+") in the dictionary, you can't have two bindings with the same name.");
return updateBinding(indexname,formula);
}
if(indexformula!=-1 && confirm("The binding '"+saved.names[indexformula]+"' has the same formula. Do you prefer to rename that one to '"+name+"'?..."))
return renameBinding(indexformula,name);
if(!confirm("Confirm the data to be saved:\nName:\n"+name+"\n\nFormula:\n"+formula))
return false;
saved.names.push(name);
saved.formulas.push(formula);
setFile(name, formula);
Android.makeNewToast("Binding saved", true).show();
return true;
}
function setFile(name, formula){
var createFile = new File(folder,name+".txt");
createFile.createNewFile();
// write to the file
var createFileWriter = new FileWriter(createFile, false);
createFileWriter.write(formula);
createFileWriter.flush();
createFileWriter.close();
}
//@return true if deleted, false if not
function deleteBinding(index){
var name=saved.names[index];
if(!confirm("Are you sure you want to delete the binding '"+ name+"'?"))
return false
saved.names.splice(index,1);
saved.formulas.splice(index,1);
new File(folder,name+".txt").delete();
Android.makeNewToast("Binding deleted", true).show();
return true;
}
//@return true if updated, false if not
function updateBinding(index, formula){
var name=saved.names[index];
if(!confirm("Are you sure you want to update the binding '"+name+"'?"))
return false;
saved.formulas[index]=formula;
setFile(name, formula);
Android.makeNewToast("Binding updated", true).show();
return true;
}
//@return true if renamed, false if not
function renameBinding(index,name){
var prename=saved.names[index];
if(prename==name) return true;
if(saved.names.indexOf(name)!=-1){
alert("There is another binding with that name, please choose a different one.");
return false;
}
if(!confirm("Are you sure you want to rename the binding '"+prename+"' to '"+name+"'?"))
return false;
saved.names[index]=name;
new File(folder,prename+".txt")
.renameTo(new File(folder,name+".txt"));
Android.makeNewToast("Binding renamed", true).show();
return true;
}
function loadSaved(){
saved = {names:[],formulas:[]};
var files=folder.listFiles();
for(var t=0;t<files.length;++t){
var file=files[t];
saved.names.push(file.getName().substring(0,file.getName().length-4));
saved.formulas.push(read(file));
}
properties=[];
for(p in Property){
if(p.substring(0,5)=="PROP_")
properties.push(p);
}
properties.sort();
}
function noItemAlert(){
alert("no item selected, please run this script from the item you want to use");
}
//cuts the input string if more than MAX characters
function cut(s){
return s.substring(0,MAX)+(s.length>MAX?"...":"")
}
//reads a file and gets the content as text
function read(file){
var r=new BufferedReader(new FileReader(file));
var s="";
var l;
while((l=r.readLine())!=null)s+=(l+"\n");
r.close();
return s.substring(0, s.length - 1);
}
//function to display a List in a Popup, where the user can select one item. Adapted from Lukas Morawietz's Multi tool script
function list(items,onClickFunction,onCancelFunction,title,data){
var builder=new AlertDialog.Builder(/*new ContextThemeWrapper(*/LL.getContext()/*, R.style.Theme_DeviceDefault)*/);
var listener=new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
setTimeout(function(){onClickFunction(which,data);},0);
return true;
}
}
var cancelListener = new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.cancel();
if(onCancelFunction!=null)
setTimeout(function(){onCancelFunction(data)},0);
}
}
builder.setItems(items,listener);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton(onCancelFunction==null?"Exit":"Back",cancelListener);//it has a Cancel Button
builder.show();
}
//Flags: custom
//Name: [!] icon saver
var path="/storage/emulated/0/LightningLauncher/Images/"
LL.bindClass("android.graphics.Bitmap");
LL.bindClass("java.io.FileOutputStream");
LL.bindClass("java.io.File");
var icon=LL.pickImage(0);
if(icon == null) return;
if(icon.isNinePatch()){
alert("This is a NinePatch and it's currently not supported by this script");
return;
}
var name=prompt("Name of the file?","file");
if(name==null) return;
var dir=new File(path);
// have the object build the directory structure, if needed.
dir.mkdirs();
var out=new FileOutputStream(path+name+".png");
icon.getBitmap().compress(Bitmap.CompressFormat.PNG,100,out);
out.close();
Android.makeNewToast("saved",true).show();
//Flags: custom
//Name: [!game] minigame find the items
var script=LL.getCurrentScript();
var data=LL.getEvent().getData();
var eventItem=LL.getEvent().getItem();
var saved=JSON.parse(script.getTag()||"[]");
for(var t=0;t<saved.length;++t)
if(LL.getItemById(saved[t])==null)
saved.splice(t--,1);
if(data=="item")clicked();
else if(saved.length!=0) help();
else newGame();
script.setTag(JSON.stringify(saved));
function newGame(){
var useall=confirm("Do you want to use all desktops? Cancel to use only the current one");
var items=LL.pickNumericValue("Choose the number of items to hide:",5,"INT",1,10,1,"items");
if(items==null) return;
var ids = [];
if(useall){
var ds=LL.getAllDesktops();
for(var t=0;t<ds.getLength();++t) add(LL.getContainerById(ds.getAt(t)));
}else{
add(LL.getCurrentDesktop());
}
function add(c){
if(ids.indexOf(c.getId()+"")!=-1) return;
ids.push(c.getId()+"");
var its=c.getItems();
for(var i=0;i<its.getLength();++i){
var it=its.getAt(i);
if(it.getType()=="Folder"||it.getType()=="Panel")add(it.getContainer());
}
}
saved=[];
var intent=Intent.parseUri("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.Dashboard;i.a=35;S.d="+script.getId()+"%2Fitem;end",0);
var icon=LL.createImage("net.pierrox.lightning_launcher_extreme", "icon");
for(var t=0;t<items;++t){
var randomc=ids[Math.floor(Math.random()*ids.length)];
var it=LL.getContainerById(randomc).addShortcut("&&&&&& GAME &&&&&",intent,0,0);
var pr=it.getProperties().edit();
pr
.setBoolean("i.rotate",false)
.setBoolean("i.enabled",true)
.setInteger("i.alpha",255)
.setString("i.pinMode","NONE")
.setBoolean("i.onGrid",false)
.setBoolean("s.labelVisibility",false)
.setBoolean("s.iconVisibility",true)
.setFloat("s.iconScale",1)
.setBoolean("s.iconReflection",false)
.setBoolean("s.iconFilter",false)
.setFloat("s.iconEffectScale",1)
.setInteger("s.iconColorFilter",-1);
pr.getBox("i.box")
.setSize("ml,mt,mr,mb,bl,bt,br,bb,pl,pt,pr,pb",0);
pr.commit();
it.setCustomIcon(icon);
it.setSize(icon.getWidth(),icon.getHeight());
it.setScale(0.5,0.5);
var box=LL.getContainerById(randomc).getBoundingBox();
var x=box.getLeft()+(box.getRight()-box.getLeft()-it.getWidth())*Math.random();
var y=box.getTop()+(box.getBottom()-box.getTop()-it.getHeight())*Math.random();
it.setPosition(x,y);
saved.push(it.getId());
}
Android.makeNewToast("Items hidden\n Gotta find them all!",false).show();
}
function clicked(){
var index=saved.indexOf(eventItem.getId());
if(index==-1){
alert("This item wasn't on my database!");
return;
}
eventItem.getParent().removeItem(eventItem);
saved.splice(index,1);
if(saved.length>0)
Android.makeNewToast("Item found! There are still "+saved.length+" item"+(saved.length==1?"":"s")+" hidden",false).show();
else alert("Congratulations! you found all hidden items");
}
function help(){
if(confirm("There are still "+saved.length+" items hidden. Do you want to see "+(saved.length==1?"it":"one of them")+"?")){
var item=saved[Math.floor(Math.random()*saved.length)];
showItemMenu(LL.getItemById(item));
}
}
function showItemMenu(item){
LL.runAction(EventHandler.EDIT_LAYOUT,item,null);
LL.runAction(EventHandler.ITEM_MENU,item,null);
}
//Flags: app
//Name: [] 3d layout viewer
//library adapted from the one here http://codentronix.com/2011/05/10/html5-experiment-a-rotating-solid-cube/
function Point3D(x,y,z) {
var point={};
point.x = x;
point.y = y;
point.z = z;
return point;
}
function rotateX(angle,point){
var rad, cosa, sina, y, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = point.y * cosa - point.z * sina;
z = point.y * sina + point.z * cosa;
return Point3D(point.x, y, z);
}
function rotateY(angle,point) {
var rad, cosa, sina, x, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = point.z * cosa - point.x * sina;
x = point.z * sina + point.x * cosa;
return Point3D(x,point.y, z);
}
function rotateZ(angle,point) {
var rad, cosa, sina, x, y;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = point.x * cosa - point.y * sina;
y = point.x * sina + point.y * cosa;
return Point3D(x, y, point.z);
}
function proyect(viewWidth, viewHeight, fov, viewDistance,point) {
var factor, x, y;
factor = fov / (viewDistance + point.z);
x = point.x * factor + viewWidth / 2;
y = point.y * factor + viewHeight / 2;
return Point3D(x, y, point.z);
}
// end library
//define
var tag="cube";
var name="viewer";
//vars
var event=LL.getEvent();
var cont=event.getContainer();//the folder container
var item=cont.getItemByName(name);
if(item==null)createfolder();//no item found, creating the whole folder
//viewer parameters
var alpha=5
var nowX=-cont.getPositionY()/alpha;
var nowY=cont.getPositionX()/alpha;
var zoom=cont.getPositionScale();
//the data
var data=cont.getTag(tag);
if(data==null)createdata();
else data=JSON.parse(data);
update();
cont.setTag(tag,JSON.stringify(data));
function createdata(){
data={vertices:[],faces:[],colors:[]};
var parent=cont.getParent();
var items=parent.getItems();
var pw=parent.getWidth()/2;
var ph=parent.getHeight()/2;
//home
data.vertices[0]=Point3D(-pw,-ph,0);
data.vertices[1]=Point3D(pw,-ph,0);
data.vertices[2]=Point3D(pw,ph,0);
data.vertices[3]=Point3D(-pw,ph,0);
data.faces[0]=[0,1,2,3];
data.colors[0]=[20,20,20];
//box
var box=parent.getBoundingBox();
data.vertices[4]=Point3D(box.getLeft()-pw,box.getTop()-ph,0);
data.vertices[5]=Point3D(box.getRight()-pw,box.getTop()-ph,0);
data.vertices[6]=Point3D(box.getRight()-pw,box.getBottom()-ph,0);
data.vertices[7]=Point3D(box.getLeft()-pw,box.getBottom()-ph,0);
data.faces[1]=[4,5,6,7];
data.colors[1]=[20,20,20];
//items
var v=data.vertices.length;
var length=items.getLength();
for(var t=0;t<length;++t){
var it=items.getAt(t);
if(it==cont.getOpener()) continue;
var itpx=it.getPositionX()-pw;
var itpy=it.getPositionY()-ph;
var itw=it.getWidth()*it.getScaleX();
var ith=it.getHeight()*it.getScaleY();
var itz=(-1-parent.getItemZIndex(it.getId()))*(pw/2+ph/2)/length;
data.vertices[v]=Point3D(itpx,itpy,itz);
data.vertices[v+1]=Point3D(itpx+itw,itpy,itz);
data.vertices[v+2]=Point3D(itpx+itw,itpy+ith,itz);
data.vertices[v+3]=Point3D(itpx,itpy+ith,itz);
data.faces.push([v,v+1,v+2,v+3]);
var type=it.getType();
data.colors.push(
type=="StopPoint"?[255,0,0]:
type=="Widget"?[0,0,255]:
type=="PageIndicator"?[255,255,255]:
type=="Panel"?[125,125,125]:
type=="Folder"?[125,255,125]:
type=="DynamicText"?[85,255,85]:
[0,255,0]
);
v=v+4
}
data.preX=nowX;
data.preY=nowY;
data.preS=zoom;
}//end createcontainer
function createfolder(){
var folder=cont.addFolder("3d view",event.getTouchX(),event.getTouchY());
var size=[cont.getWidth(),cont.getHeight()];
folder.open();
cont=folder.getContainer();//now the container is the folder itself
cont.getProperties().edit()
.setBoolean("noScrollLimit",true)
.setBoolean("noDiagonalScrolling",false)
.setEventHandler("posChanged",EventHandler.RUN_SCRIPT,LL.getCurrentScript().getId())
.setBoolean("snapToPages",false)
.commit();
item=cont.addShortcut(name,new Intent(),0,0);
item.setName(name);
item.getProperties().edit()
.setBoolean("s.labelVisibility",false)
.setBoolean("s.iconVisibility",false)
.setBoolean("i.onGrid",false)
.setString("i.pinMode","XY")
.setBoolean("i.enabled",false)
.commit();
item.setSize(size[0],size[1]);
item.setBoxBackground(LL.createImage(size[0],size[1]),"n",true);
}
function update(){
var angleX=nowX-data.preX;
var angleY=nowY-data.preY;
data.preX=nowX;
data.preY=nowY;
if(zoom!=data.preS){
data.preS=zoom;
angleX=0;
angleY=0;
}
var img=item.getBoxBackground("n");//LL.createImage(item.getWidth(),item.getHeight());
var ctx=img.draw();
var t = [];
ctx.drawRGB(0,0,0);
for( var i = 0; i < data.vertices.length; i++ ) {
var v = data.vertices[i];
var r = rotateX(angleX,rotateY(angleY,v));
data.vertices[i]=r;
var p = proyect(img.getWidth(),img.getHeight(),5000*zoom,10000,r);
t.push(p);
}
var avg_z = [];
for( var i = 0; i < data.faces.length; i++ ) {
var f = data.faces[i];
avg_z[i] = {"index":i, "z":(t[f[0]].z + t[f[1]].z + t[f[2]].z + t[f[3]].z) / 4.0};
}
avg_z.sort(function(a,b) {
return b.z - a.z;
});
for( var i = 0; i < data.faces.length; i++ ) {
var f = data.faces[avg_z[i].index]
var p=new Path();
p.moveTo(t[f[0]].x,t[f[0]].y);
p.lineTo(t[f[1]].x,t[f[1]].y);
p.lineTo(t[f[2]].x,t[f[2]].y);
p.lineTo(t[f[3]].x,t[f[3]].y);
var paint=new Paint();
paint.setARGB(255/1.5,data.colors[avg_z[i].index][0],data.colors[avg_z[i].index][1],data.colors[avg_z[i].index][2]);
ctx.drawPath(p,paint);
            }
            
img.update();
//img.save();
//item.setBoxBackground(img,"n");
}
//Flags: app
//Name: [] 3d layout viewer camera
//library adapted from the one here http://codentronix.com/2011/05/10/html5-experiment-a-rotating-solid-cube/
function Point3D(x,y,z) {
var point={};
point.x = x;
point.y = y;
point.z = z;
return point;
}
function rotateX(angle,point){
var rad, cosa, sina, y, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = point.y * cosa - point.z * sina;
z = point.y * sina + point.z * cosa;
return Point3D(point.x, y, z);
}
function rotateY(angle,point) {
var rad, cosa, sina, x, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = point.z * cosa - point.x * sina;
x = point.z * sina + point.x * cosa;
return Point3D(x,point.y, z);
}
function rotateZ(angle,point) {
var rad, cosa, sina, x, y;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = point.x * cosa - point.y * sina;
y = point.x * sina + point.y * cosa;
return Point3D(x, y, point.z);
}
function proyect(viewWidth, viewHeight, fov, viewDistance,point) {
var factor, x, y;
factor = fov / (viewDistance + point.z);
x = point.x * factor + viewWidth / 2;
y = point.y * factor + viewHeight / 2;
return Point3D(x, y, point.z);
}
function restar(a,b){
return Point3D(b.x-a.x,b.y-a.y,b.z-a.z);
}
function localworld(a,ox,oy){
return Point3D(dotprod(ox,a),dotprod(oy,a),a.z);
}
function dotprod(a,b){
return a.x*b.x+a.y*b.y+a.z*b.z;
}
function normalize(a){
var n=a.x*a.x+a.y*a.y+a.z*a.z;
n=Math.sqrt(n);
return Point3D(a.x/n,a.y/n,a.z/n);
}
// end library
//define
var tag="cube";
var name="viewer";
//vars
var event=LL.getEvent();
var cont=event.getContainer();//the folder container
var item=cont.getItemByName(name);
if(item==null)createfolder();//no item found, creating the whole folder
//viewer parameters
var alpha=5
var nowX=-cont.getPositionY()/alpha;
var nowY=cont.getPositionX()/alpha;
var zoom=cont.getPositionScale();
//the data
var data=cont.getTag(tag);
if(data==null)createdata();
else data=JSON.parse(data);
update();
cont.setTag(tag,JSON.stringify(data));
function createdata(){
data={vertices:[],faces:[],colors:[]};
var parent=cont.getParent();
var items=parent.getItems();
var pw=parent.getWidth()/2;
var ph=parent.getHeight()/2;
//home
data.vertices[0]=Point3D(-pw,-ph,0);
data.vertices[1]=Point3D(pw,-ph,0);
data.vertices[2]=Point3D(pw,ph,0);
data.vertices[3]=Point3D(-pw,ph,0);
data.faces[0]=[0,1,2,3];
data.colors[0]=[200,200,200];
//box
var box=parent.getBoundingBox();
data.vertices[4]=Point3D(box.getLeft()-pw,box.getTop()-ph,0);
data.vertices[5]=Point3D(box.getRight()-pw,box.getTop()-ph,0);
data.vertices[6]=Point3D(box.getRight()-pw,box.getBottom()-ph,0);
data.vertices[7]=Point3D(box.getLeft()-pw,box.getBottom()-ph,0);
data.faces[1]=[4,5,6,7];
data.colors[1]=[255,255,255];
//items
var v=data.vertices.length;
var length=items.getLength();
for(var t=0;t<length;++t){
var it=items.getAt(t);
if(it==cont.getOpener()) continue;
var itpx=it.getPositionX()-pw;
var itpy=it.getPositionY()-ph;
var itw=it.getWidth()*it.getScaleX();
var ith=it.getHeight()*it.getScaleY();
var itz=(1+parent.getItemZIndex(it.getId()))*(pw/2+ph/2)/length;
data.vertices[v]=Point3D(itpx,itpy,itz);
data.vertices[v+1]=Point3D(itpx+itw,itpy,itz);
data.vertices[v+2]=Point3D(itpx+itw,itpy+ith,itz);
data.vertices[v+3]=Point3D(itpx,itpy+ith,itz);
data.faces.push([v,v+1,v+2,v+3]);
var type=it.getType();
data.colors.push(
type=="StopPoint"?[255,0,0]:
type=="Widget"?[0,0,255]:
type=="PageIndicator"?[255,255,255]:
type=="Panel"?[125,125,125]:
type=="Folder"?[125,255,125]:
type=="DynamicText"?[85,255,85]:
[0,255,0]
);
v=v+4
}
//camera
data.cameraX=0;
data.cameraY=180;
//scrolling
data.preX=nowX;
data.preY=nowY;
data.preS=zoom;
}//end createcontainer
function createfolder(){
var folder=cont.addFolder("3d view",event.getTouchX(),event.getTouchY());
var size=[cont.getWidth(),cont.getHeight()];
folder.open();
cont=folder.getContainer();//now the container is the folder itself
cont.getProperties().edit()
.setBoolean("noScrollLimit",true)
.setBoolean("noDiagonalScrolling",false)
.setEventHandler("posChanged",EventHandler.RUN_SCRIPT,LL.getCurrentScript().getId())
.setBoolean("snapToPages",false)
.commit();
item=cont.addShortcut(name,new Intent(),0,0);
item.setName(name);
item.getProperties().edit()
.setBoolean("s.labelVisibility",false)
.setBoolean("s.iconVisibility",false)
.setBoolean("i.onGrid",false)
.setString("i.pinMode","XY")
.setBoolean("i.enabled",false)
.commit();
item.setSize(size[0],size[1]);
item.setBoxBackground(LL.createImage(size[0],size[1]),"n",true);
}
function update(){
var angleX=nowX-data.preX;
var angleY=nowY-data.preY;
data.preX=nowX;
data.preY=nowY;
if(zoom!=data.preS){
data.preS=zoom;
angleX=0;
angleY=0;
}
var img=item.getBoxBackground("n");//LL.createImage(item.getWidth(),item.getHeight());
var ctx=img.draw();
//camara and axis
data.cameraY=(data.cameraY+angleY)%360;
var cx=data.cameraX+angleX;
data.cameraX=cx>=90?89:cx<=-90?-89:cx;
var c=rotateY(data.cameraY,rotateX(-data.cameraX,Point3D(0,0,1)));
//var nc=normalize(c);
var ox=rotateY(data.cameraY,Point3D(1,0,0));
var oy=rotateY(data.cameraY,rotateX(-data.cameraX,Point3D(0,-1,0)));
var t = [];
ctx.drawRGB(0,0,0);
for( var i = 0; i < data.vertices.length; i++ ) {
var v = data.vertices[i];
//var r = rotateX(angleX,rotateY(angleY,v));
//data.vertices[i]=r;
var r=restar(v,c);
var p = proyect(img.getWidth(),img.getHeight(),5000*zoom,10000,localworld(r,ox,oy));
t.push(p);
}
var avg_z = [];
for( var i = 0; i < data.faces.length; i++ ) {
var f = data.faces[i];
avg_z[i] = {"index":i, "z":t[f[0]].z};
}
var zmax=10000//data.vertices[data.vertices.length-1].z;
avg_z.sort(function(a,b) {
return Math.abs(c.z*zmax - b.z)-Math.abs(c.z*zmax-a.z);
});
for( var i = 0; i < data.faces.length; i++ ) {
var f = data.faces[avg_z[i].index]
var p=new Path();
p.moveTo(t[f[0]].x,t[f[0]].y);
p.lineTo(t[f[1]].x,t[f[1]].y);
p.lineTo(t[f[2]].x,t[f[2]].y);
p.lineTo(t[f[3]].x,t[f[3]].y);
var paint=new Paint();
paint.setARGB(255/1.5,data.colors[avg_z[i].index][0],data.colors[avg_z[i].index][1],data.colors[avg_z[i].index][2]);
if(avg_z[i].index<=1){//the home and box
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
p.lineTo(t[f[0]].x,t[f[0]].y);
}
ctx.drawPath(p,paint);
            }
            
img.update();
//img.save();
//item.setBoxBackground(img,"n");
}
//Flags:
//Name: [] accelerometer
LL.bindClass("android.hardware.SensorEventListener");
LL.bindClass("android.hardware.Sensor");
var item=LL.getEvent().getItem();
var prev = 0;
var steps = 0;
var step=0;
var sube=true;
var listener = new SensorEventListener{
onAccuracyChanged:function( sensor, accuracy) {
}
, onSensorChanged:function( event) {
//Right in here is where you put code to read the current sensor values and
//update any views you might have that are displaying the sensor information
//You'd get accelerometer values like this:
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
var x, mSensorY;
/*switch (mDisplay.getRotation()) {
case Surface.ROTATION_0:*/
x = event.values[0];
mSensorY = event.values[1];/*
break;
case Surface.ROTATION_90:
mSensorX = -event.values[1];
mSensorY = event.values[0];
break;
case Surface.ROTATION_180:
mSensorX = -event.values[0];
mSensorY = -event.values[1];
break;
case Surface.ROTATION_270:
mSensorX = event.values[1];
mSensorY = -event.values[0];
}*/
var im=item.getBoxBackground("n");
var c;
if(x>0&&prev<=0){
c=0xff0000ff
steps=step;
step=0;
sube=false;
}
else if(x<0&&prev>=0){
c=0xff00ffff;
steps=step;
step=0;
sube=true;
}
else {
c=(sube?steps-step:step)/steps;
if(c>1)c=1;
if(c<0)c=0;
c=Color.rgb(255*c,255*(1-c),0);
step++;
}
prev=x;
im.draw().drawColor(c);
im.update();
//item.setLabel(steps);
}
}
var cntx=LL.getContext();
var mSensorManager = cntx.getSystemService(cntx.SENSOR_SERVICE);
var mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//return;
mSensorManager.registerListener(listener, mAccelerometer, mSensorManager.SENSOR_DELAY_NORMAL);
setTimeout(function(){
mSensorManager.unregisterListener(listener);
},10000);
//Flags: item
//Name: [] cube automatic
//code adpated from http://codentronix.com/2011/05/10/html5-experiment-a-rotating-solid-cube/
function Point3D(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
this.rotateX = function(angle) {
var rad, cosa, sina, y, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = this.y * cosa - this.z * sina;
z = this.y * sina + this.z * cosa;
return new Point3D(this.x, y, z);
}
this.rotateY = function(angle) {
var rad, cosa, sina, x, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = this.z * cosa - this.x * sina;
x = this.z * sina + this.x * cosa;
return new Point3D(x,this.y, z);
}
this.rotateZ = function(angle) {
var rad, cosa, sina, x, y;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = this.x * cosa - this.y * sina;
y = this.x * sina + this.y * cosa;
return new Point3D(x, y, this.z);
}
this.project = function(viewWidth, viewHeight, fov, viewDistance) {
var factor, x, y;
factor = fov / (viewDistance + this.z);
x = this.x * factor + viewWidth / 2;
y = this.y * factor + viewHeight / 2;
return new Point3D(x, y, this.z);
}
}
var vertices = [
new Point3D(-1,1,-1),
new Point3D(1,1,-1),
new Point3D(1,-1,-1),
new Point3D(-1,-1,-1),
new Point3D(-1,1,1),
new Point3D(1,1,1),
new Point3D(1,-1,1),
new Point3D(-1,-1,1)
];
// Define the vertices that compose each of the 6 faces. These numbers are
// indices to the vertex list defined above.
var faces  = [[0,1,2,3],[1,5,6,2],[5,4,7,6],[4,0,3,7],[0,4,5,1],[3,2,6,7]];
// Define the colors for each face.
var colors = [[255,0,0],[0,255,0],[0,0,255],[255,255,0],[0,255,255],[255,0,255]];
var angle = 0;
var item=LL.getEvent().getItem();
loop();
function loop() {
var img=LL.createImage(item.getWidth(),item.getHeight());
var ctx=img.draw();
var t = [];
ctx.drawRGB(0,0,0);
for( var i = 0; i < vertices.length; i++ ) {
var v = vertices[i];
var r = v.rotateX(angle).rotateY(angle);
var p = r.project(img.getWidth(),img.getHeight(),200,4);
t.push(p);
}
var avg_z = [];
for( var i = 0; i < faces.length; i++ ) {
var f = faces[i];
avg_z[i] = {"index":i, "z":(t[f[0]].z + t[f[1]].z + t[f[2]].z + t[f[3]].z) / 4.0};
}
avg_z.sort(function(a,b) {
return b.z - a.z;
});
for( var i = 0; i < faces.length; i++ ) {
var f = faces[avg_z[i].index]
var p=new Path();
p.moveTo(t[f[0]].x,t[f[0]].y);
p.lineTo(t[f[1]].x,t[f[1]].y);
p.lineTo(t[f[2]].x,t[f[2]].y);
p.lineTo(t[f[3]].x,t[f[3]].y);
var paint=new Paint();
paint.setARGB(255/2,colors[avg_z[i].index][0],colors[avg_z[i].index][1],colors[avg_z[i].index][2]);
ctx.drawPath(p,paint);
            }
            angle += 1;
img.update();
img.save();
item.setBoxBackground(img,"n");
if(!LL.isPaused())setTimeout(loop,1000/60);
}
//Flags: app
//Name: [] cube customrotated
//library adapted from the one here http://codentronix.com/2011/05/10/html5-experiment-a-rotating-solid-cube/
function Point3D(x,y,z) {
var point={};
point.x = x;
point.y = y;
point.z = z;
return point;
}
function rotateX(angle,point){
var rad, cosa, sina, y, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
y = point.y * cosa - point.z * sina;
z = point.y * sina + point.z * cosa;
return Point3D(point.x, y, z);
}
function rotateY(angle,point) {
var rad, cosa, sina, x, z;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
z = point.z * cosa - point.x * sina;
x = point.z * sina + point.x * cosa;
return Point3D(x,point.y, z);
}
function rotateZ(angle,point) {
var rad, cosa, sina, x, y;
rad = angle * Math.PI / 180;
cosa = Math.cos(rad);
sina = Math.sin(rad);
x = point.x * cosa - point.y * sina;
y = point.x * sina + point.y * cosa;
return Point3D(x, y, point.z);
}
function proyect(viewWidth, viewHeight, fov, viewDistance,point) {
var factor, x, y;
factor = fov / (viewDistance + point.z);
x = point.x * factor + viewWidth / 2;
y = point.y * factor + viewHeight / 2;
return Point3D(x, y, point.z);
}
// end library
//define
var tag="cube";
//vars
var event=LL.getEvent();
var cont=event.getContainer();
var item=cont.getOpener();
var data=cont.getTag(tag);
var alpha=5
var nowX=-cont.getPositionY()/alpha;
var nowY=cont.getPositionX()/alpha;
var zoom=cont.getPositionScale();
if(data==null||event.getSource()=="MENU_APP")createcontainer();
else data=JSON.parse(data);
update();
function createcube(){
data={};
data.vertices = [
Point3D(-1,1,-1),
Point3D(1,1,-1),
Point3D(1,-1,-1),
Point3D(-1,-1,-1),
Point3D(-1,1,1),
Point3D(1,1,1),
Point3D(1,-1,1),
Point3D(-1,-1,1)
];
// Define the vertices that compose each of the 6 faces. These numbers are
// indices to the vertex list defined above.
data.faces  = [[0,1,2,3],[1,5,6,2],[5,4,7,6],[4,0,3,7],[0,4,5,1],[3,2,6,7]];
// Define the colors for each face.
data.colors = [[255,0,0],[0,255,0],[0,0,255],[255,255,0],[0,255,255],[255,0,255]];
data.preX=nowX;
data.preY=nowY;
}//end createcube
function createcontainer(){
data={vertices:[],faces:[],colors:[]};
var parent=item.getParent();
var items=parent.getItems();
var pw=parent.getWidth()/2;
var ph=parent.getHeight()/2;
var v=0;
for(var t=0;t<items.getLength();++t){
var it=items.getAt(t);
if(it==item) continue;
var itpx=it.getPositionX()-pw;
var itpy=it.getPositionY()-ph;
var itw=it.getWidth();
var ith=it.getHeight();
var itz=-parent.getItemZIndex(it.getId())*(pw/2+ph/2)/items.getLength();
data.vertices[v]=Point3D(itpx,itpy,itz);
data.vertices[v+1]=Point3D(itpx+itw,itpy,itz);
data.vertices[v+2]=Point3D(itpx+itw,itpy+ith,itz);
data.vertices[v+3]=Point3D(itpx,itpy+ith,itz);
data.faces.push([v,v+1,v+2,v+3]);
var type=it.getType();
data.colors.push(
type=="StopPoint"?[255,0,0]:
type=="Widget"?[0,0,255]:
type=="PageIndicator"?[255,255,255]:
type=="Panel"?[125,125,125]:
type=="Folder"?[125,255,125]:
type=="DynamicText"?[85,255,85]:
[0,255,0]
);
v=v+4
}
data.preX=nowX;
data.preY=nowY;
preparecontainer();
}//end createcontainer
function preparecontainer(){
item.setBoxBackground(LL.createImage(1,1),"ns",true);
cont.getProperties().edit()
.setBoolean("noScrollLimit",true)
.setBoolean("noDiagonalScrolling",false)
.setEventHandler("posChanged",EventHandler.RUN_SCRIPT,LL.getCurrentScript().getId())
.commit();
}
function update(){
var angleX=nowX-data.preX;
var angleY=nowY-data.preY;
data.preX=nowX;
data.preY=nowY;
var img=LL.createImage(item.getWidth(),item.getHeight());
var ctx=img.draw();
var t = [];
ctx.drawRGB(0,0,0);
for( var i = 0; i < data.vertices.length; i++ ) {
var v = data.vertices[i];
var r = rotateX(angleX,rotateY(angleY,v));
data.vertices[i]=r;
var p = proyect(img.getWidth(),img.getHeight(),5000*zoom,10000,r);
t.push(p);
}
var avg_z = [];
for( var i = 0; i < data.faces.length; i++ ) {
var f = data.faces[i];
avg_z[i] = {"index":i, "z":(t[f[0]].z + t[f[1]].z + t[f[2]].z + t[f[3]].z) / 4.0};
}
avg_z.sort(function(a,b) {
return b.z - a.z;
});
for( var i = 0; i < data.faces.length; i++ ) {
var f = data.faces[avg_z[i].index]
var p=new Path();
p.moveTo(t[f[0]].x,t[f[0]].y);
p.lineTo(t[f[1]].x,t[f[1]].y);
p.lineTo(t[f[2]].x,t[f[2]].y);
p.lineTo(t[f[3]].x,t[f[3]].y);
var paint=new Paint();
paint.setARGB(255/1.5,data.colors[avg_z[i].index][0],data.colors[avg_z[i].index][1],data.colors[avg_z[i].index][2]);
ctx.drawPath(p,paint);
            }
            
img.update();
img.save();
item.setBoxBackground(img,"ns");
cont.setTag(tag,JSON.stringify(data));
}
//Flags:
//Name: [] custom menu tests
// function to execute when a menu item is clicked
function handler(v) {
// close the menu and display the selected item as well as the text of the selected menu item
menu.close();
alert(item+" / " +
v.getText());
}
// it is possible to read the current menu mode and configure it accordingly
if(menu.getMode() == Menu.MODE_ITEM_NO_EM) {
// optional, clear the content of the menu, comment this line to keep the standard items before to add new ones
menu.getMainItemsView().removeAllViews();
// add a few items
menu.addMainItem("Hello", handler);
menu.addMainItem("Goodbye", handler);
}
//Flags:
//Name: [] enlarge and go
var item=LL.getEvent().getItem();
var cont=item.getParent();
var panel=cont.getItemByName(item.getLabel());
//start animation
//zoom
cont.setPosition(Math.abs(item.getPositionX()),Math.abs(item.getPositionY()),Math.abs(cont.getHeight())/item.getHeight(),true);
setTimeout(function(){
//set containers
panel.setCell(0,0,5,4);//hard coded
var items=cont.getItems();
for(var t=0;t<items.getLength();++t){
var it=items.getAt(t);
if(it.getType()=="Panel" && it.getName()!=item.getLabel()) it.setCell(-5+t*5,-4,0+t*5,0);//hard coded
}
//move to real container
cont.setPosition(0,0,1,false);
updateImage();
},500);
function updateImage(){
//update background
if(true){
var ns=item.getBoxBackground("ns");
var f=item.getBoxBackground("f");
if(ns==null||f==null||ns.getHeight()!=cont.getHeight()){
ns=LL.createImage(cont.getWidth(),cont.getHeight());
f=LL.createImage(cont.getWidth(),cont.getHeight());
item.setBoxBackground(ns,"ns",true);
item.setBoxBackground(f,"f",true);
}
var cns=ns.draw();
var cf=f.draw();
var pclear = new Paint();
pclear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
cf.drawPaint(pclear);
//canv.setScale(
cont.getView().draw(cf);
f.update();
cns.drawPaint(pclear);
cns.drawBitmap(f.getBitmap(),0,0,null);
ns.update()
//ns.save()
//c.save()
}
}
//Flags:
//Name: [] File manager in panel
var path="/";
var containerId=0x7b;
//binds
LL.bindClass("java.io.File");
LL.bindClass("java.io.FileWriter");
LL.bindClass("android.os.Environment");
LL.bindClass("android.webkit.MimeTypeMap");
var event=LL.getEvent();
var scriptId=LL.getCurrentScript().getId();
var path= event.getData() || event.getItem().getTag() || Environment.getExternalStorageDirectory()+path;
var current=new File(path);
if(event.getItem().getTag("createFile")!=null){
var name;
if((name=prompt("Name of file:",""))!=null){
var newfile=(new File(current,name));
newfile.createNewFile();
LL.startActivity(intentFromFile(newfile));
}else return;
}else if(event.getItem().getTag("createDir")!=null){
var name;
if((name=prompt("Name of dir:",""))!=null){
var newfile=(new File(current,name));
newfile.mkdir();
current=newfile;
}else return;
}else if(current.isFile()){
LL.startActivity(intentFromFile(current));
return;
}
var files=current.listFiles();
if(files==null){
Toast.makeText(LL.getContext(),"Error loading folder "+path,Toast.LENGTH_LONG).show();
return;
}
var container=LL.getContainerById(containerId);
var items=container.getItems();
for(var t=0;t<items.getLength();++t){
container.removeItem(items.getAt(t));
}
files.sort(sortingFunction);
var icon_folder=LL.createImage("android", "ic_menu_archive");
var icon_new=LL.createImage("android", "create_contact");
var intent= Intent.parseUri("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.Dashboard;i.a=35;S.d="+scriptId+";end",0);
for(var t=-3;t<files.length;++t){
var shr=container.addShortcut("", intent,0,0);
shr.setCell(0,t+3,1,t+4,true);
if(t==-3){
shr.setTag(current.getParent());
shr.setLabel("UP",true);
shr.setImage(LL.createImage("android", "ic_menu_revert"));
}else if(t==-2){
shr.setTag(path);
shr.setTag("createDir","1");
shr.setLabel("CREATE NEW DIR",true);
shr.setImage(icon_new);
}else if(t==-1){
shr.setTag(path);
shr.setTag("createFile","1");
shr.setLabel("CREATE NEW FILE",true);
shr.setImage(icon_new);
}else if(files[t].isFile()){
shr.setTag(files[t].getPath());
shr.setLabel("File: "+files[t].getName(),true);
}else{
shr.setTag(files[t].getPath());
shr.setLabel("Dir: "+files[t].getName(),true);
shr.setImage(icon_folder);
}
}
container.getOpener().getContainer().setPosition(0,0);
function intentFromFile(file){
var intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),getMimeType(file.getName()));
var j = Intent.createChooser(intent, "Choose an application to open with:");
return j;//startActivity(j);
}
function getMimeType(url)
{
var parts=url.split(".");
var extension=parts[parts.length-1];
var type = null;
var mime = MimeTypeMap.getSingleton();
if (extension != null) {
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
function sortingFunction(a,b){
if(a.isFile()!=b.isFile()){
return a.isFile()?1:-1;
}
return a.getName().toLowerCase()>b.getName().toLowerCase()?1:-1;
}
//Flags: app item
//Name: [] full container screenshot
var path="/storage/emulated/0/LightningLauncher/Images/"
var timeout=500;
LL.bindClass("android.graphics.Bitmap");
LL.bindClass("java.io.FileOutputStream");
LL.bindClass("java.io.File");
//vars
var c=LL.getEvent().getContainer();
var view = c.getView();
var box=c.getBoundingBox();
var bwidth=box.getRight()-box.getLeft();
var bheight=box.getBottom()-box.getTop();
var cwidth=c.getWidth();
var cheight=c.getHeight();
var image=LL.createImage(bwidth,bheight);
var canvas=image.draw();
//save current position
var pos=[c.getPositionX(),c.getPositionY(),c.getPositionScale()];
if(!confirm("This will create a screenshot of this container. Please wait until 'Done' shows")) return;
//disable the onchange script if any
var onchange={event: c.getProperties().getEventHandler("posChanged") , script:-1 , enable:false};
if(onchange.event.getAction()==EventHandler.RUN_SCRIPT){
onchange.script= LL.getScriptById( parseFloat(onchange.event.getData()) );
if(!onchange.script.hasFlag(Script.FLAG_DISABLED) ){
onchange.enable=true;
onchange.script.setFlag(Script.FLAG_DISABLED,true);
}
}
//unpin all items and move them if necessary
var items=c.getItems();
var state=[];
var itempos=[];
for(var t=0;t<items.getLength();++t){
var it=items.getAt(t);
state[t]=it.getProperties().getString("i.pinMode");
if(state[t]!="NONE"){
var preimage=null;//committing undoes live image, we preserve it
if(it.getType()=="Shortcut")preimage=it.getImage();
it.getProperties().edit().setString("i.pinMode","NONE").commit();
if(preimage!=null)it.setImage(preimage);
//save item data
itempos[t]=savepos(it);
var itposx=it.getPositionX()/pos[2];
var itposy=it.getPositionY()/pos[2];
//set scale
it.setScale(it.getScaleX()/pos[2],it.getScaleY()/pos[2]);
//modify position
if(state[t].indexOf("X")!=-1) itposx+=pos[0];
if(state[t].indexOf("Y")!=-1) itposy+=pos[1];
//apply position
it.setPosition(itposx,itposy);
}//end state!="NONE"
}//end for
//create all timeouts
var time=timeout;
for(var x=0;x<bwidth;x+=cwidth)
for(var y=0;y<bheight;y+=cheight){
eval("setTimeout(function(){save("+x+","+y+");},time);");
time+=timeout;
}
//last timeout
setTimeout(finish,time);
function finish(){
// have the object build the directory structure, if needed.
var dir=new File(path);
dir.mkdirs();
//save to file
image.update();
image.save();
image.getBitmap().compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(path+"container"+c.getId()+".png"));
//restore onchange script
if(onchange.enable){
onchange.script.setFlag(Script.FLAG_DISABLED,false);
}
//restore pinned mode
for(var t=0;t<items.getLength();++t){
var it=items.getAt(t);
if(state[t]!="NONE"){
it.getProperties().edit().setString("i.pinMode",state[t]).commit();
applypos(itempos[t],it)
}
}
//reset view
c.setPosition(pos[0],pos[1],pos[2],false);
LL.save();
Android.makeNewToast("Done", true).show();
}
//save the image of each part
function save(x,y){
c.setPosition(box.getLeft()+x,box.getTop()+y,1,false);
//save image
canvas.drawBitmap(getBitmap(view),x,y,null);
}
//get the bitmap to copy it in the full image
function getBitmap(view) {
//Define a bitmap with the same size as the view
var returnedBitmap = LL.createImage(cwidth,cheight);
//Bind a canvas to it
var canvas = returnedBitmap.draw();
/*
//Get the view's background
var bgDrawable =view.getBackground();
if (bgDrawable!=null)
//has background drawable, then draw it on the canvas
bgDrawable.draw(canvas);
else
//does not have background drawable, then draw white background on the canvas
canvas.drawColor(Color.WHITE);
*/
// draw the view on the canvas
view.draw(canvas);
//return the bitmap
returnedBitmap.update();
returnedBitmap.save();
return returnedBitmap.getBitmap();
}
function savepos(it){
var dat={};
if(it.getProperties().getBoolean("i.onGrid")){
dat.grid=true;
dat.cell=it.getCell();
it.getProperties().edit().setBoolean("i.onGrid",false).commit();
}else{
dat.grid=false;
dat.x=it.getPositionX();
dat.y=it.getPositionY();
dat.scalex=it.getScaleX();
dat.scaley=it.getScaleY();
}
return dat;
}
function applypos(dat,it){
if(dat.grid){
it.getProperties().edit().setBoolean("i.onGrid",true).commit();
it.setCell(dat.cell.getLeft(),dat.cell.getTop(),dat.cell.getRight(),dat.cell.getBottom());
}else{
it.setScale(dat.scalex,dat.scaley);
it.setPosition(dat.x,dat.y);
}
}
//Flags: app item
//Name: [] hide when launched
/* Settings */
// Time that needs to pass to be fully opaque again
var SECONDS = 60*30; // in seconds
// Minimum alpha, aka alpha just when clicked
var MINIMUM = 50; // between 0 (fully transparent) and 255 (fully opaque)
/* end settings */
var TARGET = "i.alpha";
var EVENT = "i.tap";
var FORMULA = "Math.min(255,255-(%timestamp%+%seconds%-$ll_timestamp)/(%seconds%)*(255-%minimum%))";
var item=getEvent().getItem();
var source=getEvent().getSource();
if(source=="MENU_ITEM"){
if(isInstalled(item)){
if(confirm("Do you want to remove the script from this item?")){
uninstallItem(item);
toast("Uninstalled");
}
}else{
if(confirm("Do you want to set the script in this item?")){
install(item);
toast("Installed");
}
}
} else if(source=="MENU_APP"){
var container=getEvent().getContainer();
if(isInstalled(container)){
if(confirm("Do you want to remove the script from the container?")){
uninstallContainer(container);
toast("Uninstalled");
}
}else{
if(confirm("Do you want to set the script in the container?")){
install(container);
toast("Installed");
}
}
} else if(source=="I_CLICK"){
onClick();
} else{
toast("Unimplemented source: "+source);
}
function onClick(){
item.setBinding(TARGET,
FORMULA.replace(/%timestamp%/g,Date.now()/1000)
.replace(/%seconds%/g,SECONDS)
.replace(/%minimum%/g,MINIMUM),
true);
if('launch' in item) item.launch();
}
function install(element){
element.getProperties().edit()
.setEventHandler(EVENT, EventHandler.RUN_SCRIPT, getCurrentScript().getId())
.commit();
}
function uninstallItem(item){
item.unsetBinding(TARGET);
item.getProperties().edit()
.setEventHandler(EVENT, EventHandler.UNSET, null)
.setInteger(TARGET,255)
.commit();
}
function uninstallContainer(container){
container.getProperties().edit()
.setEventHandler(EVENT, EventHandler.UNSET, null)
.commit();
var items=container.getItems();
for(var t=0;t<items.length;t++){
var item=items.getAt(t);
item.unsetBinding(TARGET);
item.getProperties().edit()
.setInteger(TARGET,255)
.commit();
}
}
function isInstalled(element){
var e=element.getProperties().getEventHandler(EVENT);
return e!=null
&& e.getAction() == EventHandler.RUN_SCRIPT
&& e.getData() != null
&& e.getData().lastIndexOf(getCurrentScript().getId(),0) === 0;
}
//Flags: item
//Name: [] improved menu
// it is possible to read the current menu mode and configure it accordingly
toast(menu.getMode())
if(menu.getMode() == Menu.MODE_ITEM_NO_EM) {
menu.addMainItem("App shortcuts",shortcuts);
}
function shortcuts(){
toast("shortcuts")
}
//Flags: app
//Name: [] labyrinth
var width=3;
var height=3;
var wallsize=20;
var cont=LL.getEvent().getContainer();
//create the panel with the properties
//create the labyrinth holder
var lab=[];
for(var t=0;t<width;++t){
lab[t]=[];
for(var tt=0;tt<height;++tt){
lab[t][tt]={
l:false,//down
t:false,//right
r:false,//up
b:false//left
};
//virtual labyrinth creation. Method cell-by-cell
var rand=Math.floor(Math.random()*2)+1;
/*
0:none
1:bottom
2:right
3:both
*/
if( (tt==height-1 || (rand&2)==2 ) && t!=width-1 )lab[t][tt].r=true;
if( (t==width-1 || (rand&1)==1 ) && tt!=height-1 )lab[t][tt].b=true;
if(t!=0)lab[t][tt].l=lab[t-1][tt].r;
if(tt!=0)lab[t][tt].t=lab[t][tt-1].b;
}
}
//physical creation start
for(var t=0;t<width;++t){
for(var tt=0;tt<height;++tt){
//create the items with the borders
var it=cont.addShortcut(t+" "+tt,new Intent(),0,0);
it.setCell(t*2,tt*2,t*2+2,tt*2+2,true);
var cell=lab[t][tt];
var border= (cell.l?"":"bl,")+(cell.t?"":"bt,")+(cell.r?"":"br,")+(cell.b?"":"bb,");
if(border!=""){
var prop=it.getProperties().edit();
prop.getBox("i.box").setSize(border,wallsize);
prop.commit();
}
}
}
//Flags:
//Name: [] launch by swipe
bindClass("android.R")
var x = event.getX();
var y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
pre = null
//break
case MotionEvent.ACTION_MOVE:
var it=getSelected();
if(it==null || pre==null || (pre!=null && it.getId()!=pre.getId())){
if(it!=null){
select(it);
}
if(pre!=null){
unselect(pre)
}
pre=it;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
var it=getSelected();
pre = null;
if(it!=null){
unselect(it);
try{it.launch();}catch(e){}
}
break;
default:
alert(event.getAction())
}
return true;
function getSelected(){
var cx = x+item.getPositionX();
var cy = y+item.getPositionY();
var items = item.getParent().getItems();
for(var t=items.length-1;t>=0;--t){
var it=items.getAt(t);
if(it.getProperties().getBoolean("i.enabled") && it.getId()!=item.getId() && isInside(it,cx,cy)){
return it;
}
}
return null;
}
function isInside(it,cx,cy){
var bb=[it.getPositionX(),it.getPositionY(),0,0]
bb[2]=bb[0]+it.getWidth();
bb[3]=bb[1]+it.getHeight();
return bb[0]<=cx && cx<=bb[2] && bb[1]<=cy && cy<=bb[3];
}
function select(item){
try{
item.getRootView().getBackground().setState([ R.attr.state_pressed, R.attr.state_enabled ]);
}catch(e){}
}
function unselect(item){
try{
item.getRootView().getBackground().setState([]);
}catch(e){}
}
//Flags: app item
//Name: [] most used app drawer
//start config
var increase = 1.2
var decrease = 0.99;
var name="most used";
var tag="most used";
var id=1;//id of the container where the panel will be placed
//end config
var event=LL.getEvent();
var item=event.getItem();
var source=event.getSource();
var scriptid=LL.getCurrentScript().getId();
var drawer=LL.getContainerById(99);
var panel=LL.getContainerById(id).getItemByName(name);
if(source=="MENU_APP" || panel==null || item==null){
var noexist= (panel==null);
if(!confirm("This will set all the tap action of all the containers from the app drawer to run this script." + ( noexist?" And will add a 'most used apps' panel at the top.":"") + "\n Do you want to continue?")){
if(confirm("Do you want instead to uninstall the script?")){
uninstall();
}
return;
}
install();
return;
}
panel=panel.getContainer();
if(source=="I_CLICK"){
if(item.getType()=="Folder")tappedFolder(item);
if(item.getType()=="Shortcut")tappedItem(item);
return;
}
if(source=="MENU_ITEM" && item.getParent()==panel){
deleteItem(item);
return;
}
//else
Android.makeNewToast("Run the script from the menu app", true).show();
function install(){
if(noexist){
panel=LL.getContainerById(id).addPanel(0,0,drawer.getWidth(),1);
LL.save();
panel.setName(name);
panel.getContainer().getProperties().edit().setInteger("gridPRowNum",1).commit();
prepareContainer(panel.getContainer(),true);
}
//LL.save();
prepareContainer(drawer,true);
}
function uninstall(noexist){
if(!noexist)LL.getContainerById(id).removeItem(panel);
LL.save();
prepareContainer(drawer,false);
}
function prepareContainer(cont,install){
var handler= install? EventHandler.RUN_SCRIPT : EventHandler.UNSET;
var items=cont.getItems();
for(var t=0;t<items.getLength();++t){
var item=items.getAt(t);
if(item.getType()=="Folder" || item.getType()=="Panel")prepareContainer(item.getContainer(),install);
}
cont.setTag(tag, install? 1 : null);
cont.getProperties().edit().setEventHandler("i.tap",handler,scriptid).commit();
}
function tappedItem(tapped){
var component=tapped.getIntent().toURI();
var items=panel.getItems();
var list=[];
var exists=false;
for(var t=0;t<items.getLength();++t){
var item=items.getAt(t);
list[t]=item;
if(component==item.getIntent().toURI()){
item.setTag(tag, Math.min(item.getTag(tag)*increase,2) );
exists=true;
}else{
item.setTag(tag, Math.max(item.getTag(tag)*decrease,0.5) );
}
//item.setLabel(item.getTag(tag));
}//end for
if(!exists){
var added=panel.addShortcut(tapped.getLabel(),tapped.getIntent(),0,0);
added.setTag(tag,1);
added.setDefaultIcon(tapped.getDefaultIcon());
list.push(added);
}
update(list);
tapped.launch()
}
function update(list){
if(list==null){
var items=panel.getItems();
list=[];
for(var t=0;t<items.getLength();++t) list[t]=items.getAt(t);
}
list.sort(function(a,b){return b.getTag(tag)-a.getTag(tag);});
for(var t=0;t<list.length;++t){
list[t].setCell(t,0,t+1,1,true);
}//end for
}//end function
function tappedFolder(folder){
if(folder.getContainer().getTag(tag)==null) prepareContainer(folder.getContainer(),true);
folder.launch();
}
function deleteItem(item){
if(confirm("Do you want to delete this item?"))panel.removeItem(item);
update();
}
//Flags: custom
//Name: [] notification no autokill
//bind classes
bindClass("android.app.Notification");
bindClass("android.app.NotificationManager");
bindClass("android.app.NotificationChannel");
bindClass("android.R");
//vars
var cntx=getBackgroundScreen().getContext();//if you need a 'context' for a java function, this is something you can use.
var nm=cntx.getSystemService(cntx.NOTIFICATION_SERVICE);//returns the service used to work with notifications
var id="nokill";
if(false){
//delete channel and exit
nm.deleteNotificationChannel(id);
return;
}
//oreo
nm.createNotificationChannel(new NotificationChannel(id,"Avoid being killed",NotificationManager.IMPORTANCE_LOW));
//create the notification from a builder
var n=Notification.Builder(cntx,id)//start the builder
.setContentTitle("Lightning is running")//title
.setContentText("Notification used to avoid lightning being killed. You can disable this notification channel to hide the notification")//main text
.setSmallIcon(R.color.transparent)
.setOngoing(true)
.build();//finish the builder and returns a ready notification
nm.notify(0,n);//show the notification. If you want to show more than one you need to set a different first number for each
//Flags: app custom
//Name: [] Notifications
//bind classes
LL.bindClass("android.app.Notification");
LL.bindClass("android.app.NotificationManager");
LL.bindClass("android.content.Context");
LL.bindClass("android.app.PendingIntent");
LL.bindClass("android.R");
//vars used also in the returned functions
var cntx=LL.getContext();//if you need a 'context' for a java function, this is probably what you need.
var nm=cntx.getSystemService(Context.NOTIFICATION_SERVICE);//returns the service used to work with notifications
//oreo fix
bindClass("android.app.NotificationChannel");
cntx.getSystemService(cntx.NOTIFICATION_SERVICE).createNotificationChannel(new NotificationChannel("script","Scripts",2));
//if data passed, evaluate the data as code
if((data=LL.getEvent().getData())!=null){
eval("function toeval(){"+data+"\n}");
toeval();//encapsulating the code inside a function instead of evaluating it directly allows to make alerts and such
return;
}
//if there wasn't data, create the notification
var id=0;//single identifier for each pending intent, used in the helper function
//create the notification from a builder
var n=Notification.Builder(cntx,"script")//start the builder
.setContentTitle("A notification")//title
.setContentText("This is a demo of how to make a notification.")//main text
.setContentInfo("notification demo")//information
//.setSmallIcon(R.drawable.ic_dialog_info)//small icon
.setSmallIcon(R.color.transparent)
.setContentIntent(makeintent("main();"))//when launch
.setSubText("commentary")//secondary text
.setDeleteIntent(makeintent("dismissed();"))//when dismissed
.setAutoCancel(false)//set to true to cancel when clicking
.addAction(R.drawable.ic_menu_save,"Accept2",makeintent("accept();"))//extra button
.addAction(0,"direct",makeintent("alert('This alert is evaluated directly');"))//extra button
.addAction(R.drawable.ic_menu_close_clear_cancel,"Cancel",makeintent("cancel();"))//another extra button
//.setOngoing(true)
//.setStyle(new BigTextStyle())
//you can add more things like sound, vibration, color...
//search 'notification.builder'
.build();//finish the builder and returns a ready notification
nm.notify(0,n);//show the notification. If you want to show more than one you need to set a different first number for each
//help function to make pending notifications
function makeintent(data){
var intent=new Intent().getIntent("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.Dashboard;i.a=35;end")//'launch a script' shortcut
intent.putExtra('d',LL.getCurrentScript().getId()+"/"+data);//which script and data
return PendingIntent.getActivity(cntx,id++,intent,0x8000000);//the pending intent ready to be used. each one with different id, and flag to refresh existing one
}
//functions, used to better structure of the code
function main(){
alert("Notification clicked, now...do things");
//things
}
function accept(){
alert("accepted");
//nm.cancel(0);//this removes the notification
}
function cancel(){
Android.makeNewToast("canceled",true).show();
nm.cancel(0);//this removes the notification
}
function dismissed(){
Android.makeNewToast("Vital testing apparatus destroyed.",false).show();
//if you didn't get it, it's from Portal ;)
}
//Flags: custom
//Name: [] preferences
var types=["Color","CheckBox","List"]
bindClass("android.app.AlertDialog");
["ListView"].concat(types).forEach(function(v){
bindClass("net.pierrox.lightning_launcher.prefs.LLPreference"+v);
});
var screen = getActiveScreen();
var context = screen.getContext();
var preferences = [];
var selector = new LLPreferenceList(0, "Add...", ["Choose..."].concat(types), 0, null);
// create a list view to display our preferences
var listView = new LLPreferenceListView(context, null);
listView.setListener({
onLLPreferenceChanged:onSelected
});
update();
// setup the dialog and assign its content view with the preference list view
var builder=new AlertDialog.Builder(context);
builder.setView(listView);
builder.setTitle("Preference editor");
builder.setPositiveButton("Save",{onClick:onSave});
builder.setNegativeButton("Back", null);
builder.show();
function onSelected(pref){
if(pref!=selector || pref.getValueIndex()==0) return;
var type=types[pref.getValueIndex()-1];
preferences.push( new self["LLPreference"+type](0,type) );
update()
}
function update(){
listView.setPreferences(preferences.concat([selector]));
}
function onSave(dialog,id){
dialog.dismiss();
}
//Flags: app item
//Name: [] style tool
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface");
var script=LL.getCurrentScript();
var item=LL.getEvent().getItem();
var container=LL.getEvent().getContainer();
var saved=script.getTag();
if(self.StyleScript==undefined)
initialize();
var options=["Get and save data from Item","Get and save data from Container","Apply saved data to Item","Apply saved data to Container"];
if(item==null) options[0]=options[2]="-no item selected-";
if(container==null) options[1]=options[3]="-no container selected-";
if(saved==null) options[2]=options[3]="-no saved data-";
dialog();
function dialog(){
showList(options,f_manageSelected,"Choose");
}
function f_manageSelected(index){
switch(index){
case 0:
if(item!=null) saveAndShow(item);
else dialog();
break;
case 1:
if(container!=null) saveAndShow(container);
else dialog();
break;
case 2:
if(item!=null&&saved!=null) applyTo(item);
else dialog();
break;
case 3:
if(container!=null&&saved!=null) applyTo(container);
else dialog();
break;
}
}
function saveAndShow(item){
var properties= StyleScript.getProperties(item);
script.setTag(JSON.stringify(properties));
prompt(item,StyleScript.toCode(properties));
}
function applyTo(item){
var err=StyleScript.applyPropertiesToItem(JSON.parse(saved),item);
if(err!="")alert("Errors:\n"+err);
}
//function to display a List in a Popup, where the user can select one item. Adapted from Lukas Morawietz's Multi tool script
function showList(items,onClickFunction,title){
var builder=new AlertDialog.Builder(/*new ContextThemeWrapper(*/LL.getContext()/*, R.style.Theme_DeviceDefault)*/);
var listener=new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
setTimeout(function(){onClickFunction(which);},0);
return true;
}
}
var cancelListener = new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.cancel();
}
}
builder.setItems(items,listener);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",null);//it has a Cancel Button
builder.show();
}
/*
* #############################################
* ## Initialization of the StyleScript class ##
* #############################################
*/
function initialize(){
self.StyleScript={
/**
* Converts the object properties into a script representation
*/
toCode:function(data){
var string="var p=item.getProperties().edit();\n";
for(var i=0;i<data.prop.length;++i){
switch(data.type[i]){
case "Box":
string+='var pbox=p.getBox("'+data.prop[i]+'");\n';
var box=data.value[i];
//sizes
for(var t=0;t<box.size.value.length;++t){
string+='pbox.setSize("'+box.size.prop[t]+'",'+box.size.value[t]+");\n";
}//end box for
//colors
for(var t=0;t<box.color.value.length;++t){
string+='pbox.setColor("'+box.color.prop[t]+'","'+box.color.state[t]+'",'+box.color.value[t]+');\n';
}
//alignment
string+='pbox.setAlignment("'+box.alignment.h+'","'+box.alignment.v+'");\n';
break;
default:
string+=(string[string.length-2]==";"?"p":"")+".set"+data.type[i]+'("'+data.prop[i]+'",'+(data.type[i]=="String"?'"'+data.value[i]+'"':data.value[i])+")\n";
}//end switch
}//end data.prop for
return string+(string[string.length-2]==";"?"p":"")+".commit();";
}//end toCode function
,
/**
* Returns the object properties of the item
*/
getProperties:function(item){
var data={prop:[],type:[],value:[]};
for(type in this.properties){
if(!(item==LL.getContainerById(99)&&type=="AppDrawer")){
LL.bindClass("net.pierrox.lightning_launcher.script.api."+type);
if(self[type]==null) continue;//just in case
if(!(item instanceof self[type]) && type=="Container" ) continue;
}//end app drawer check
for(prop in this.properties[type]){
var proptype = this.properties[type][prop];
proptype=proptype=="int"?"Integer":proptype.charAt(0).toUpperCase() + proptype.slice(1);
var value;
try{
value=item.getProperties()["get"+proptype](prop);
}catch(e){continue};
switch(proptype){
case "Box":
var boxdata={size:{prop:[],value:[]},color:{prop:[],value:[],state:[]},alignment:{h:0,v:0}};
for(var t=0;t<this.boxsizes.length;++t){
var sizeprop=this.boxsizes[t];
var sizevalue=value.getSize(sizeprop);
var index=boxdata.size.value.indexOf(sizevalue);
if(index!=-1){
boxdata.size.prop[index]+=","+sizeprop;
}else{
boxdata.size.prop.push(sizeprop);
boxdata.size.value.push(sizevalue);
}
}//end prop sizes
//colors
for(var t=0;t<this.boxcolors.length;++t){
var colorprop=this.boxcolors[t];
var tempdata={value:[],state:[]};
for(var tt=0;tt<this.boxstates.length;++tt){
var state=this.boxstates[tt];
var colorvalue = value.getColor(colorprop,state);
var index=tempdata.value.indexOf(colorvalue);
if(index!=-1){
tempdata.state[index]+=","+state;
}else{
tempdata.state.push(state);
tempdata.value.push(colorvalue);
}
}//end boxstate
//same color&state
for(var s=0;s<boxdata.color.value.length;++s)
for(var ss=0;ss<tempdata.value.length;++ss){
if(boxdata.color.value[s]==tempdata.value[ss]
&& boxdata.color.state[s]==tempdata.state[ss]){
boxdata.color.prop[s]+=","+colorprop;
tempdata.value[ss]=null;
}
}//end doble for s ss
//different color|state
for(var ss=0;ss<tempdata.value.length;++ss){
if(tempdata.value[ss]==null) continue;
boxdata.color.prop.push(colorprop);
boxdata.color.value.push(tempdata.value[ss]);
boxdata.color.state.push(tempdata.state[ss]);
}
}//end prop colors
//alignment
boxdata.alignment.h=value.getAlignmentH();
boxdata.alignment.v=value.getAlignmentV();
data.value.push(boxdata);
break;
case "EventHandler":
data.value.push([
"EventHandler."+this.eventHandlerPairs[value.getAction()]
,value.getData()!=null?'"'+value.getData()+'"':"null"
]);
//continue; //not supported yet
break;
default:
data.value.push(value);
}//end switch
data.prop.push(prop);
data.type.push(proptype);
}//end prop for
}//end types for
return data;
}//end getProperties function
,
/**
* Applies the properties (the object) to the item.
* Returns the properties that couldn't be applied as string
*/
applyPropertiesToItem:function(properties,item){
var errors="";
var p,pbox;
this.toCode(properties)
.replace(/\n\./g,"\np.")
.replace(/var (.*)=/g,"$1=null;\n$1=")
.split("\n")
.map(function(v){
eval("function toEval(){"+v+"}");
try{toEval()}catch(e){errors+=v+"\n"}
});
return errors;
}
,
/**
* Contains the list of properties of each type
*/
properties:{
"Container":
{
"newOnGrid":"boolean",
"allowDualPosition":"boolean",
"gridPColumnMode":"string",
"gridPColumnNum":"int",
"gridPColumnSize":"int",
"gridPRowMode":"string",
"gridPRowNum":"int",
"gridPRowSize":"int",
"gridLColumnMode":"string",
"gridLColumnNum":"int",
"gridLColumnSize":"int",
"gridLRowMode":"string",
"gridLRowNum":"int",
"gridLRowSize":"int",
"gridPL":"boolean",
"gridLayoutModeHorizontalLineColor":"int",
"gridLayoutModeHorizontalLineThickness":"float",
"gridLayoutModeVerticalLineColor":"int",
"gridLayoutModeVerticalLineThickness":"float",
"gridAbove":"boolean",
"bgSystemWPScroll":"boolean",
"bgSystemWPWidth":"int",
"bgSystemWPHeight":"int",
"bgColor":"int",
"statusBarHide":"boolean",
"statusBarColor":"int",
"navigationBarColor":"int",
"statusBarOverlap":"boolean",
"navigationBarOverlap":"boolean",
"screenOrientation":"string",
"scrollingDirection":"string",
"overScrollMode":"string",
"noDiagonalScrolling":"boolean",
"pinchZoomEnable":"boolean",
"snapToPages":"boolean",
"fitDesktopToItems":"boolean",
"autoExit":"boolean",
"rearrangeItems":"boolean",
"swapItems":"boolean",
"freeModeSnap":"string",
"useDesktopSize":"boolean",
"noScrollLimit":"boolean",
"wrapX":"boolean",
"wrapY":"boolean",
"iconPack":"string",
"homeKey":"EventHandler",
"menuKey":"EventHandler",
"longMenuKey":"EventHandler",
"backKey":"EventHandler",
"longBackKey":"EventHandler",
"searchKey":"EventHandler",
"bgTap":"EventHandler",
"bgDoubleTap":"EventHandler",
"bgLongTap":"EventHandler",
"swipeLeft":"EventHandler",
"swipeRight":"EventHandler",
"swipeUp":"EventHandler",
"swipeDown":"EventHandler",
"swipe2Left":"EventHandler",
"swipe2Right":"EventHandler",
"swipe2Up":"EventHandler",
"swipe2Down":"EventHandler",
"orientationPortrait":"EventHandler",
"orientationLandscape":"EventHandler",
"posChanged":"EventHandler",
"load":"EventHandler",
"paused":"EventHandler",
"resumed":"EventHandler"
},
"AppDrawer":
{
"adHideActionBar":"boolean",
"adDisplayABOnScroll":"boolean",
"adDisplayedModes":"int",
"adActionBarTextColor":"int"
},
"Item":
{
"i.box":"Box",
"i.rotate":"boolean",
"i.selectionEffect":"string",
"i.selectionEffectMask":"boolean",
"i.enabled":"boolean",
"i.alpha":"int",
"i.pinMode":"string",
"i.filterTransformed":"boolean",
"i.onGrid":"boolean",
"i.hardwareAccelerated":"boolean",
"i.tap":"EventHandler",
"i.longTap":"EventHandler",
"i.swipeLeft":"EventHandler",
"i.swipeRight":"EventHandler",
"i.swipeUp":"EventHandler",
"i.swipeDown":"EventHandler",
"i.touch":"EventHandler",
"i.paused":"EventHandler",
"i.resumed":"EventHandler",
"i.itemAdded":"EventHandler",
"i.itemRemoved":"EventHandler"
},
"Shortcut":
{
"s.labelVisibility":"boolean",
"s.labelFontColor":"int",
"s.selectionColorLabel":"int",
"s.focusColorLabel":"int",
"s.labelFontSize":"float",
"s.labelFontTypeFace":"string",
"s.labelFontStyle":"string",
"s.labelMaxLines":"int",
"s.iconVisibility":"boolean",
"s.iconScale":"float",
"s.iconReflection":"boolean",
"s.iconReflectionOverlap":"float",
"s.iconReflectionSize":"float",
"s.iconReflectionScale":"float",
"s.iconFilter":"boolean",
"s.labelVsIconPosition":"string",
"s.labelVsIconMargin":"int",
"s.labelShadow":"boolean",
"s.labelShadowRadius":"float",
"s.labelShadowOffsetX":"float",
"s.labelShadowOffsetY":"float",
"s.labelShadowColor":"int",
"s.iconEffectScale":"float",
"s.iconColorFilter":"int"
},
"Folder":
{
"f.titleVisibility":"boolean",
"f.titleFontColor":"int",
"f.titleFontSize":"float",
"f.animationIn":"string",
"f.animationOut":"string",
"f.animFade":"boolean",
"f.iconStyle":"string",
"f.autoClose":"boolean",
"f.closeOther":"boolean",
"f.wAH":"string",
"f.wAV":"string",
"f.wX":"int",
"f.wY":"int",
"f.wW":"int",
"f.wH":"int",
"f.box":"Box",
"f.autoFindOrigin":"boolean"
},
"PageIndicator":
{
"p.style":"string",
"p.rawFormat":"string",
"p.dotsMarginX":"int",
"p.dotsMarginY":"int",
"p.dotsOuterRadius":"int",
"p.dotsInnerRadius":"int",
"p.dotsOuterStrokeWidth":"int",
"p.dotsOuterColor":"int",
"p.dotsInnerColor":"int",
"p.miniMapOutStrokeColor":"int",
"p.miniMapOutFillColor":"int",
"p.miniMapOutStrokeWidth":"int",
"p.miniMapInStrokeColor":"int",
"p.miniMapInFillColor":"int",
"p.miniMapInStrokeWidth":"int",
"p.lineBgWidth":"int",
"p.lineBgColor":"int",
"p.lineFgWidth":"int",
"p.lineFgColor":"int",
"p.lineGravity":"string"
},
"CustomView":
{
"v.onCreate":"string",
"v.onDestroy":"string"
}
}
,
/**
* Contains the properties of all sizes of a box
*/
boxsizes:["ml","mt","mr","mb","bl","bt","br","bb","pl","pt","pr","pb"]
,
/**
* Contains the properties of all colors of a box
*/
boxcolors:["c","bl","bt","br","bb"]
,
/**
* Contains the states of the colors of a box
*/
boxstates:["n","s","f"]
,
/**
* Contains the list of event handlers where the index is the id (initialized below)
*/
eventHandlerPairs:[]
};
//initialize
var keys= Object.keys(EventHandler);
for(var t=0;t<keys.length;++t)
StyleScript.eventHandlerPairs[EventHandler[keys[t]]]=keys[t];
Android.makeNewToast("StyleScript class initialized",true).show();
}//end initialize function
/*
This is a small code that I used to get the list of properties from the web page.
var text=prompt("","");
text="{\n"
+text.split("\n").map(function(v){
if(v.trim()=="") return null;
if(v.match("properties:")!=null) return '},"'+v.split(" properties:")[0].split(" ").map(function(v){return v[0].toUpperCase()+v.slice(1);}).join("")+'":{';
if(v.match("Name|:")!=null)return null;
return v.split(/\s+/g).splice(0,2).map(function(v){return '"'+v+'"'}).join(":");}).join(",\n")
.slice(2)
.replace(/\n(\,\n)+/g,"\n")
.replace(/\{\,*\n*\,+/g,"{")
.replace(/\,+\n*\,*\}/g,"\n}")
+"\n}";
prompt('',text);
*/
//Flags: app item
//Name: [] V2 full container screenshot
var path="/storage/emulated/0/LightningLauncher/Images/"
var showStopPoints=false;
var showInvisible=false;
LL.bindClass("android.graphics.Bitmap");
LL.bindClass("java.io.FileOutputStream");
LL.bindClass("java.io.File");
//vars
var c=LL.getEvent().getContainer();
var cwidth=c.getWidth();
var cheight=c.getHeight();
var box=c.getBoundingBox();
var boxleft=box.getLeft();
var boxtop=box.getTop();
var boxwidth=box.getRight()-boxleft;
var boxheight=box.getBottom()-boxtop;
var image=LL.createImage(boxwidth,boxheight);
var canvas=image.draw();
//current position
var pos=[c.getPositionX(),c.getPositionY(),c.getPositionScale()];
var name=prompt("This will create a screenshot of this container. Please wait until 'Done' shows. \n\n Which name do you want the picture to have?","container"+c.getId());
if(name==null)return;
//draw the container background if any
var background=c.getView().getBackground();
if(background!=null)canvas.draw(background,pos[0],pos[1],null);
//draw each item
var items=c.getItems();
for(var t=0;t<items.getLength();++t){
var it=items.getAt(t);
var ittype=it.getType();
if(
(ittype=="StopPoint"&&!showStopPoints)
||
(!it.isVisible()&&!showInvisible)
) continue;
//get image
var itimage=getBitmap(it.getRootView());
//position
var posx=it.getPositionX();
var posy=it.getPositionY();
//due to pinned mode, the real position is a bit different
var itpinmode=it.getProperties().getString("i.pinMode");
if(itpinmode!="NONE"){
posx=posx/pos[2];
posy=posy/pos[2];
//resize bitmap
itimage=resize(itimage,1/pos[2]);
//modify position
if(itpinmode.indexOf("X")!=-1) posx+=pos[0];
if(itpinmode.indexOf("Y")!=-1) posy+=pos[1];
}//end pinmode
//draw in the master bitmap
posx-=boxleft;
posy-=boxtop;
if(ittype=="StopPoint"){
posx-=it.getWidth()/2;
posy-=it.getHeight()/2;
}
canvas.drawBitmap(itimage,posx,posy,null);
}//end for
// have the object build the directory structure, if needed.
var dir=new File(path);
dir.mkdirs();
//save to file
image.update();
image.save();
image.getBitmap().compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(path+name+".png"));
Android.makeNewToast("Done", true).show();
//get the bitmap to copy it in the full image
function getBitmap(view) {
//Define a bitmap with the same size as the view
var returnedBitmap = LL.createImage(view.getWidth(),view.getHeight());
//Bind a canvas to it
var canvas = returnedBitmap.draw();
//Get the view's background
var bgDrawable =view.getBackground();
if (bgDrawable!=null)
//has background drawable, then draw it on the canvas
bgDrawable.draw(canvas);
// draw the view on the canvas
view.draw(canvas);
//return the bitmap
returnedBitmap.update();
returnedBitmap.save();
return returnedBitmap.getBitmap();
}
function resize(bitmap,scale){
return Bitmap.createScaledBitmap(bitmap,bitmap.getWidth()*scale,bitmap.getHeight()*scale,false);
}
//Flags:
//Name: [deprecated] Fast run tool old
Android.makeNewToast("This fast run tool is deprecated\nlaunched from "+LL.getEvent().getContainer()+" - "+LL.getEvent().getItem(), true).show();
return
/*Available vars*/
var e = LL.getEvent();//event
var c = e.getContainer();//container
var i = e.getItem();//item
var cntx = LL.getContext();//context
/*end of available vars*/
/*available functions*/
//helper function to show a toast in a shorter way
function Toast(say){
if(say==null)say="null";
Android.makeNewToast(say,false).show();
}
//helper function to bind a class in a shorter way
function bind(class){
return LL.bindClass(class);
}
//deprecated. sets and returns the item default tag
function iTag(setnew){
if(setnew!=undefined){
if(setnew=='null')setnew=null; i.setTag(setnew);
}
return i.getTag();
}
//deprecated. sets and returns the container default tag
function cTag(setnew){
if(setnew!=undefined){
if(setnew=='null')setnew=null; c.setTag(setnew);
}
return c.getTag();
}
//evaluates the func function for each item in container (c if null)
function foreach(func,container){
if(container==null)container=c;
var items=container.getItems();
for(var t=0;t<items.getLength();++t)func(items.getAt(t));
}
//this returns a string with the properties/methods of the object.
//optionally will only return those with 'search' in it
function objects(obj,search){
if(obj==""||obj==null) return "";//no valid object
var keys=Object.keys(obj);//magic line ;)
keys.sort();
var text="";//the output
for(t in keys){
var key=keys[t];
var prop=""+obj[key];//when calling that key
if(search!=null&&key.indexOf(search)==-1&&prop.indexOf(search)==-1)continue;//searching not found
text+=key+" : "+prop+"\n";
if(prop[prop.length-1]!="\n")text+="\n";
}
return text;
}
/*end of available functions*/
//run from data
var datatorun=LL.getEvent().getData();
if(datatorun!=null&&datatorun!=""){
eval("function fastRunTool(){\n"+datatorun+"\n}");
fastRunTool();
return;
}
//if no data to run, use the inputted one
if(datatorun==""){
eval("function fastRunTool(){\n"+LL.getScriptTag()+"\n}");
fastRunTool();
return;
}
//normal run
var repeat=true;//will allow to run again after an error
while(repeat){repeat=false;
var text = LL.getScriptTag() || "";
//this asks for the code to run
var out = prompt(
"Vars: e-event, cntx-context"+
(c!=null? ", c-container":", [no container]")+
(i!=null? ", i-item":", [no item]")+
"\n"+
"Functions:  Toast(String)"+
", boolean bind(string)"+
//(c!=null ? ", String cTag(String)":"")+
//(i!=null ? ", String iTag(String)":"")+
", void foreach(function(item),{container (c)})"+
", String objects(object,{search})"+
"\n\nPrevious input:\n"+
text+
"\n_____________________________________"
,text);
//Change this 'line' if you want
if(out==null) return;//cancel
LL.setScriptTag(out);//save
//gets the last line.
var last=out.lastIndexOf("\n")+1;//
var line=out.substr(last);
//If no ';' , '}' or '//' found encapsulate it inside a prompt
if(line.search(/(\;|\}|\/\/)/)==-1) out=out.substr(0,last)+"prompt('»"+line.replace(/'/g,"\\'")+"«',toStringFormatted("+line+"));";
//evaluates the code
out="function fastRunTool(){"+out+"\n}";
try{
eval(out);
fastRunTool();
}catch(e){
//error found. Showing and repeating
repeat=prompt(LL.getScriptTag().split("\n").map(function(v,i,a){return ":"+(i+1)+":"+v;}).join("\n"),e)!=null;
}
}//end of repeat
//custom functions
//returns the input as string or as a formatted string if already
function toStringFormatted(a){
return typeof a!="string" ? ""+a : '"'+a.replace(/"/g,'\\"')+'"' ;
}
//Flags: app item
//Name: [deprecated] fix oreo icons
var ROUNDVAL=-1; //radius of corners. 0 to have square items. 1 to have circle ones. Any inbetween to have rounded squares. -1 for system setting
var ZOOM=1.5; //zoom of the foreground icon relative to background. 1 for original size (small). 2 for double size (big). Any inbetween for different size.
bindClass("android.graphics.drawable.LayerDrawable");
var cntx=LL.getContext();
var ask=false;
var override=false;
var event=getEvent();
var source=event.getSource();
if(source=="MENU_APP"){
ask=false;
override=confirm("Do you want to override all icons found? Cancel to change only unset ones");
fixContainer(event.getContainer());
}else if(source=="MENU_ITEM"){
ask=true;
fixIcon(event.getItem());
}else{
fixContainer(event.getContainer());
}
function canOverride(){
if(ask){
return confirm("This will override the custom icon. You want to continue?");
}else{
return override;
}
}
function fixContainer(c){
var items=c.getItems();
for(var t=0;t<items.getLength();++t){
var item=items.getAt(t);
if(item.getType()=="Shortcut") fixIcon(item);
if(item.getType()=="Panel"||item.getType()=="Folder") fixContainer(item.getContainer());
}
}
function fixIcon(i){
try{
var icon = cntx.getPackageManager().getApplicationIcon(i.getIntent().getComponent().getPackageName());
}catch(e){
return;
}
if(icon.class.toString()=="class android.graphics.drawable.AdaptiveIconDrawable" && ( i.getCustomIcon()==null || canOverride())){
try{
var layerDrawable = new LayerDrawable([icon.getBackground(),icon.getForeground()]);
var width = layerDrawable.getIntrinsicWidth()/ZOOM;
var height = layerDrawable.getIntrinsicHeight()/ZOOM;
var image=Image.createImage(width,height);
var canv=image.draw();
var path = new Path();
if(ROUNDVAL>=1){
path.addCircle(width / 2, height/ 2, Math.min(width/2, height / 2), Path.Direction.CCW);
}else if(ROUNDVAL>=0){
path.addRoundRect(0,0,width,height,width*ROUNDVAL/2,height*ROUNDVAL/2,Path.Direction.CCW)
}else{
var matrix=new Matrix();
matrix.setScale(width/100,height/100);
path=icon.getIconMask()
path.transform(matrix);
}
canv.clipPath(path);
layerDrawable.setBounds(-width*(ZOOM-1)/ZOOM, -height*(ZOOM-1)/ZOOM, width*(2*ZOOM-1)/ZOOM, height*(2*ZOOM-1)/ZOOM);
layerDrawable.draw(canv);
i.setDefaultIcon(image);
//Android.makeNewToast("icon changed: "+i,true).show();
}catch(e){
Android.makeNewToast("error on icon: "+i,true).show();
alert(e)
}
}
}
//Flags: custom
//Name: [javascript] corrupted text
var rango=[0x300,0x36f];
function randchar(n){
var c="";
for(var i=0;i<n;++i)
c+=String.fromCharCode(rango[0]+Math.random()*(rango[1]+1-rango[0]));
return c
}
var text=prompt("text","");
var max=LL.pickNumericValue("max",10,"INT",1,50,1,"");
var output="";
for(var t=0;t<text.length;++t){
output+=text[t];
var r=t/text.length;
r*=r;
if(Math.random()<r)output+=randchar(Math.random()*r*max);
}
prompt("output",output);
//Flags: item custom
//Name: [JavaScript] Descifrador
var inp = LL.getScriptTag() || "";
text = prompt("Text:",inp);
if(text==null)return;
LL.setScriptTag(text);
text=text.toUpperCase();
var outp="";
var english = !confirm("Use ñ?");
var letters = english? "ABCDEFGHIJKLMNOPQRSTUVWXYZ" : "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ";
var n = letters.length;
for(var av = 0 ; av<n;++av){
var prov=text;
for(var c = 0 ; c<n;++c){
eval("prov=prov.replace(/"+ letters[c]+"/g,'"+letters[(c+n-av)%n].toLowerCase()+"');");
}
outp+=letters[av]+"("+letters[(n-av)%n]+"): "+prov+"\n";
}
prompt("From(To) A to(from)",outp);
if(!confirm("Show affine now?")) return;
outp="";
//calculate aes
var aes=[];
var invaes=[];
out:for(var a=1;a<n;++a){
var inv=0;
for(var p=1;p<=a;++p){
if((a*p)%n==1)
if(inv==0) inv=p;
else continue out;
}
if(inv!=0){
aes.push(a);
invaes.push(inv);
}
}
for(var ia = 0 ; ia<aes.length;++ia){
for(var bes = 0; bes<n;++bes){
var prov=text;
for(var c = 0 ; c<n;++c){
eval("prov=prov.replace(/"+ letters[c]+"/g,'"+letters[(invaes[ia]*(c-bes+n))%n].toLowerCase()+"');");
}
outp+="A="+aes[ia]+",B="+bes+":\n"+prov+"\n";
}
}
prompt("Affine:",outp.toLowerCase());
/*
var list="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var input=prompt("text","");
var cifrar=confirm("cifrar?");
var index=0;
if(cifrar){
index=parseFloat(prompt("n","0"));
}else{
index=-list.indexOf(input[0]);
}
var output="";
if(cifrar){
output+=list[index];
}
for(var t=cifrar?0:1;t<input.length;++t){
var n=list.indexOf(input[t]);
output+= n==-1?input[t]: list[(n+index+list.length)%list.length];
index=(index+(cifrar?1:-1)+list.length)%list.length;
}
prompt(input,output);
*/
//Flags: app
//Name: [LLXperiment] iwatch
var e=LL.getEvent();
var c=e.getContainer();
if(e.getSource()!="C_POSITION_CHANGED"){additems();return}
var bb=c.getBoundingBox();
var size=[bb.getRight()-bb.getLeft(),bb.getTop()-bb.getBottom()];
var center=[c.getPositionX()+c.getWidth()*c.getPositionScale()/2,c.getPositionY()+c.getHeight()*c.getPositionScale()/2];
var max=Math.min(c.getWidth()/2,c.getHeight()/2);
var items=c.getItems();
for(var t=0;t<items.getLength();++t){
var item=items.getAt(t);
if(item.getType()!="Shortcut")continue;
compute(item);
}
function compute(i){
var d=getDistance(i.getPositionX()+i.getWidth()*i.getScaleX()/2,i.getPositionY()+i.getHeight()*i.getScaleY()/2);
var s=Math.max(0.1,(1-d/max)*2)
i.setScale(s,s);
}
function getDistance(x,y){
var dist=9999999;
for(var px=-1;px<=1;++px)
for(var py=-1;py<=1;++py)
dist=Math.min(dist,rad(x,y,center[0]+px*size[0],center[1]+py*size[1]));
return dist
}
function rad(a,b,c,d){
return Math.sqrt(Math.pow(a-c,2)+Math.pow(b-d,2));
}
function additems(){
var its=c.getItems();
/*
for(var ii=0;ii<its.getLength();++ii)c.removeItem(its.getAt(ii));
*/
var itsp=0;
var l=150;//horiz
var ix=5;
var iy=6;//even
var ll=l*Math.sqrt(3)/2;
for(var y=0;y<iy;++y){
var s=(y%2==0)?l/4:l*3/4;
for(var x=0;x<ix;++x){
var sh=its.getAt(itsp++)//c.addShortcut("",new Intent(),0,0);
sh.setSize(l,ll);
sh.setScale(1,1);
sh.setPosition(s+x*l-sh.getWidth()*sh.getScaleX()/2,ll/2+ll*y-sh.getHeight()*sh.getScaleY()/2);
//sh.setCustomIcon(LL.pickImage(0));
}
}
var p=c.getOpener();
p.setSize(l*ix,ll*iy);
}
//Flags:
//Name: [LLXperiment] LLX Snake
/*
LLXperiment
Snake game
made by TrianguloY
*/
var cont=LL.getEvent().getContainer();
var click=LL.getEvent().getItem();
if(click==null){
if(LL.getScriptTag()!=null){
//on positionchange event
var dir="";
if(cont.getPositionX()<0)dir="r";
else if(cont.getPositionX()>0)dir="l";
else if(cont.getPositionY()<0)dir="d";
else if(cont.getPositionY()>0)dir="u";
if(dir!="")LL.setScriptTag(dir);
}
//if(dir!="")Android.makeNewToast(dir,false).show();
cont.setPosition(0,0,1,false);
return;
}
//onclick to stop
if(LL.getScriptTag()!=null){
LL.setScriptTag(null);
//alert("stopped");
return;
}
if(click.getLabel()!="LLX Snake"){
click.launch();
return;
}
//Start game
//vars
var tick = 500;
var n=1;
var xs = [click.getCell().getLeft()];
var ys = [click.getCell().getTop()];
var xn=-1;
var yn=-1;
var hor = Math.floor(cont.getWidth()/cont.getCellWidth()+0.1);
var ver = Math.floor(cont.getHeight()/cont.getCellHeight()+0.1);
LL.setScriptTag("");
var dir="";
//items
var items = cont.getItems();
if(items.getLength()<n){alert("Place more items please");return;}
var cells = [];
var apple = [0,0];
setapple();
for(var i=items.getLength()-1;i>=0;--i){
//save cells
cells[i]=items.getAt(i).getCell();
//initial position
if(i<n)items.getAt(i).setCell(xs[i],ys[i],xs[i]+1,ys[i]+1);
else if(i==n)items.getAt(i).setCell(apple[0],apple[1],apple[0]+1,apple[1]+1);
else items.getAt(i).setCell(-1,-1,0,0);
}
//start iterations
snakenext();
//functions
function snakenext(){
var prev = dir;
dir= LL.getScriptTag();
if(dir==null||LL.isPaused()){
//when stopped, restore cells
for(var i=items.getLength()-1;i>=0;--i){
items.getAt(i).setCell(cells[i].getLeft(),cells[i].getTop(), cells[i].getRight() ,cells[i].getBottom() );
}
return;
}
//forbidden directions
if(prev=="r"&&dir=="l")dir="r";
if(prev=="l"&&dir=="r")dir="l";
if(prev=="u"&&dir=="d")dir="u";
if(prev=="d"&&dir=="u")dir="d";
//direction
var dead=false;
xn=xs[0];
yn=ys[0];
switch(dir[0]){
case 'r': ++xn; if(xn>=hor)dead=true; break;
case 'l': --xn; if(xn<0) dead=true ; break;
case 'd': ++yn; if(yn>=ver) dead=true ; break;
case 'u': --yn; if(yn<0) dead=true ; break;
}
if(dead) end("Screen walls, Ouch");
//apple?
if(xn==apple[0] && yn==apple[1]){
++n;
if(n>=items.getLength()||n>=hor*ver){
--n;
end("You win!");
}
setapple();
items.getAt(n).setCell(apple[0],apple[1],apple[0]+1,apple[1]+1);
tick*=0.9;
}
//me? (tail)
if(check(xn,yn)) end("Oops, you can't eat yourself");
//move the tail
for(var i=n-1;i>=1;--i){
items.getAt(i).setCell(xs[i-1],ys[i-1],xs[i-1]+1,ys[i-1]+1);
xs[i]=xs[i-1];
ys[i]=ys[i-1];
}
//move the head
items.getAt(0).setCell(xn,yn,xn+1,yn+1);
xs[0]=xn; ys[0]=yn;
//repeat...and repeat and repeat and so on
setTimeout(snakenext,tick);
}
function setapple(){
var flag = true;
while(flag){
apple[0]=Math.floor(Math.random()*hor);
apple[1]=Math.floor(Math.random()*ver);
flag = check(apple[0],apple[1]) || (apple[0]==xn&&apple[1]==yn);
}
}
function check(x,y){
flag=false;
for(var i=0;i<n-1;++i)
if(x==xs[i] && y==ys[i]){
flag=true;
break;
}
return flag;
}
function end(message){
LL.setScriptTag(null);
alert(message);
}
//Flags:
//Name: [lutz] movement core
/*
var t={}
t.ItemIds=[0x6f001f]
t.ItemsX1=[0];
t.ItemsX2=[500];
t.ItemsY1=[0];
t.ItemsY2=[500];
t.RootId=c.getId()
LL.runScript("[lutz] movement core",JSON.stringify(t));
*/
// ============================================================
// Configuration
// Animation Style:
// "L"inear: linear movement
// "P"ow: x^power
// "E"xpo: exponential with base 2
// "B"ack: little bounce
var fxAnim="P";
// Ease Curve:
// "In": decelerate until end
// "Out": accelerate until end
// "InOut": accelerate and decelerate
// "Auto": automatically determine best ease curve
var fxEase="InOut";
// Strength of curve:
// default 6 for "P"ow (2 to 10)
// default 1.618 for "B"ack (1.0 to 2.0)
var fxPower=6;
// Authentic Motion in/out ratio
// More natural motion when using Ease InOut
// see: http://www.google.com/design/spec/animation/authentic-motion.html
var fxEaseRatio=null;
// Animation delay per step in milliseconds
var animDelay = 0;
// Steps to use for animation
var animSteps = 16;
// Evaluate event
var evt = LL.getEvent();
var eSrc = evt.getSource();
// ============================================================
// Override default configuration with global settings
var dtCfg = JSON.parse(LL.getCurrentDesktop().getTag("AnimCfg")||"null");
if (dtCfg==null) dtCfg = {};
fxAnim = "FxAnim" in dtCfg ? dtCfg.FxAnim : fxAnim;
fxEase = "FxEase" in dtCfg ? dtCfg.FxEase : fxEase;
fxPower = "FxPower" in dtCfg ? dtCfg.FxPower : fxPower;
fxEaseRatio = "FxEaseRatio" in dtCfg ? dtCfg.FxEaseRatio : fxEaseRatio;
animDelay = "AnimDelay" in dtCfg ? dtCfg.AnimDelay : animDelay;
animSteps = "AnimSteps" in dtCfg ? dtCfg.AnimSteps : animSteps;
// ============================================================
// Override default configuration with script parameters
var jsStr = evt.getData();
//alert(jsStr);
var param = JSON.parse(jsStr||"null");
if (param==null) param = {};
fxAnim = "FxAnim" in param ? param.FxAnim : fxAnim;
fxEase = "FxEase" in param ? param.FxEase : fxEase;
fxPower = "FxPower" in param ? param.FxPower : fxPower;
fxEaseRatio = "FxEaseRatio" in param ? param.FxEaseRatio : fxEaseRatio;
animDelay = "AnimDelay" in param ? param.AnimDelay : animDelay;
animSteps = "AnimSteps" in param ? param.AnimSteps : animSteps;
// General settings
var idRoot = "RootId" in param ? param.RootId : null;
// Item settings
var itemIds = "ItemIds" in param ? param.ItemIds : [];
if(itemIds.length==0)
return; // No items? Just exit...
// ============================================================
// Initialize missing parameters
var isOffsetAbsolute = "OffsetIsAbsolute" in param ? param.OffsetIsAbsolute : false;
var itemsType = "ItemsType" in param ? param.ItemsType : [];
var itemsX1 = "ItemsX1" in param ? param.ItemsX1 : [];
var itemsX2 = "ItemsX2" in param ? param.ItemsX2 : [];
var itemsY1 = "ItemsY1" in param ? param.ItemsY1 : [];
var itemsY2 = "ItemsY2" in param ? param.ItemsY2 : [];
var itemsA1 = "ItemsA1" in param ? param.ItemsA1 : [];
var itemsA2 = "ItemsA2" in param ? param.ItemsA2 : [];
var itemsZ = "ItemsZ" in param ? param.ItemsZ : [];
var itemsAnimOffset = "ItemsAnimOffset" in param ? param.ItemsAnimOffset : [];
var itemsFxSteps = "ItemsFxSteps" in param ? param.ItemsFxSteps : [];
var itemsFxAnim = "ItemsFxAnim" in param ? param.ItemsFxAnim : [];
var itemsFxEase = "ItemsFxEase" in param ? param.ItemsFxEase : [];
var itemsFxPower = "ItemsFxPower" in param ? param.ItemsFxPower : [];
var itemsFxAnim2 = "ItemsFxAnim2" in param ? param.ItemsFxAnim2 : [];
var itemsFxEase2 = "ItemsFxEase2" in param ? param.ItemsFxEase2 : [];
var itemsFxPower2 = "ItemsFxPower2" in param ? param.ItemsFxPower2 : [];
//alert(JSON.stringify(param));
// ============================================================
// Fill up arrays to match lengths
while (itemsType.length<itemIds.length) { itemsType.push("I"); }
while (itemsX1.length<itemIds.length) { itemsX1.push(null); }
while (itemsX2.length<itemIds.length) { itemsX2.push(null); }
while (itemsY1.length<itemIds.length) { itemsY1.push(null); }
while (itemsY2.length<itemIds.length) { itemsY2.push(null); }
while (itemsZ.length<itemIds.length) { itemsZ.push(null); }
while (itemsA1.length<itemIds.length) { itemsA1.push(null); }
while (itemsA2.length<itemIds.length) { itemsA2.push(null); }
while (itemsAnimOffset.length<itemIds.length) { itemsAnimOffset.push(0); }
while (itemsFxSteps.length<itemIds.length) { itemsFxSteps.push(null); }
while (itemsFxAnim.length<itemIds.length) { itemsFxAnim.push(fxAnim); }
while (itemsFxEase.length<itemIds.length) { itemsFxEase.push(fxEase); }
while (itemsFxPower.length<itemIds.length) { itemsFxPower.push(fxPower); }
while (itemsFxAnim2.length<itemIds.length) { itemsFxAnim2.push(null); }
while (itemsFxEase2.length<itemIds.length) { itemsFxEase2.push(null); }
while (itemsFxPower2.length<itemIds.length) { itemsFxPower2.push(null); }
// ============================================================
// Get root container
var dt = idRoot!=null
? LL.getContainerById(idRoot)
: LL.getCurrentDesktop();
//alert(dt);
var dtW = Math.round(dt.getWidth());
var dtH = Math.round(dt.getHeight());
var dtY = Math.round(dt.getPositionY());
var dtX = Math.round(dt.getPositionX());
var dtRows = dt.getProperties().getInteger("gridPRowNum");
var dtRowH = Math.round(dtH/dtRows);
var dtCols = dt.getProperties().getInteger("gridPColumnNum");
var dtColW = Math.round(dtW/dtCols);
// ============================================================
// Detach from grid etc.
var DetachItem = function(i) {
if (i.getProperties().getBoolean("i.onGrid")) {
// Workaround: sometimes after detaching position or dimension is wrong...
var x=i.getPositionX();
var y=i.getPositionY();
var h=i.getHeight();
var w=i.getWidth();
i.getProperties().edit().setBoolean("i.onGrid",false).commit();
i.setPosition(x,y);
i.setSize(w,h);
}
}
// ============================================================
// Get items and calculate movement ranges
var items = [];
var itemsDeltaX = [];
var itemsDeltaY = [];
var itemsDeltaA = [];
var totalAnimOffset = 0;
var maxAnimSteps = 0;
for(var idx=0;idx<itemIds.length;idx++) {
var item = dt.getItemById(itemIds[idx]);
if (item!=null) {
DetachItem(item);
}
if (itemsType[idx]=="C" && item.getType()=="Panel") {
// Get container instead of item
item = item.getContainer();
}
items.push(item);
if (item!=null) {
//if (itemsX1[idx]==null) { itemsX1[idx]=item.getPositionX(); }
//if (itemsY1[idx]==null) { itemsY1[idx]=item.getPositionY(); }
// Set initial position
if ((itemsX1[idx]!=null &&
itemsX1[idx]!=item.getPositionX()) ||
(itemsY1[idx]!=null &&
itemsY1[idx]!=item.getPositionY())) {
item.setPosition(itemsX1[idx],itemsY1[idx]);
}
//if (itemsZ[idx]==null) { itemsZ[idx]=dt.getItemZIndex(itemIds[idx]); }
if (itemsA1[idx]==null) {
itemsA1[idx]=item.getProperties().getInteger("i.alpha");
}
}
if (itemsX2[idx]==null) { itemsX2[idx]=itemsX1[idx]; }
if (itemsY2[idx]==null) { itemsY2[idx]=itemsY1[idx]; }
if (itemsA2[idx]==null) { itemsA2[idx]=itemsA1[idx]; }
var itemDeltaX=(itemsX1[idx]==null||itemsX2[idx]==null)
? null : itemsX1[idx]-itemsX2[idx];
var itemDeltaY=(itemsY1[idx]==null||itemsY2[idx]==null)
? null : itemsY1[idx]-itemsY2[idx];
itemsDeltaX.push(itemDeltaX);
itemsDeltaY.push(itemDeltaY);
itemsDeltaA.push(itemsA1[idx]-itemsA2[idx]);
// Ease = "Auto"?
if (itemsFxEase[idx]=="Auto") {
itemsFxEase[idx]=Math.abs(itemDeltaX)<Math.abs(itemDeltaY)
?(itemDeltaX<0?"In":"Out")
:(itemDeltaX<0?"Out":"In");
itemsFxEase2[idx]=itemsFxEase[idx];
if(itemDeltaX!=null && itemDeltaX>0) {
// X-Movement always linear
itemsFxAnim2[idx]=itemsFxAnim[idx];
itemsFxAnim[idx]="L";
} else {
itemsFxAnim2[idx]="L";
}
}
if(isOffsetAbsolute) {
if(itemsAnimOffset[idx]!=null &&
totalAnimOffset<itemsAnimOffset[idx]) {
totalAnimOffset=itemsAnimOffset[idx];
}
} else {
var itemOffset = itemsAnimOffset[idx]!=null?itemsAnimOffset[idx]:0;
// Offset between 0 and 1 means offset relative to animSteps
if (itemOffset>0.0 && itemOffset<1.0) {
itemOffset = Math.round(animSteps * itemOffset);
}
totalAnimOffset+=itemOffset;
itemsAnimOffset[idx]=totalAnimOffset;
}
var animStepsItem = itemsFxSteps[idx]!=null?itemsFxSteps[idx]:animSteps;
if (maxAnimSteps < animStepsItem+totalAnimOffset) {
maxAnimSteps = animStepsItem+totalAnimOffset;
}
if(itemsFxAnim2[idx]==null&&itemsFxAnim[idx]!=null) { itemsFxAnim2[idx]=itemsFxAnim[idx]; }
if(itemsFxEase2[idx]==null&&itemsFxEase[idx]!=null) { itemsFxEase2[idx]=itemsFxEase[idx]; }
if(itemsFxPower2[idx]==null&&itemsFxPower[idx]!=null) { itemsFxPower2[idx]=itemsFxPower[idx]; }
}
// ============================================================
// Animations
// ============================================================
var FxAnim = {
Linear:function(p,x){return p;},
Pow:function(p,x){return Math.pow(p,x&&x||6);},
Expo:function(p,x){return Math.pow(2,8*(p-1));},
Back:function(p,x){x=x&&x||1.618;return Math.pow(p,2)*((x+1)*p-x);}
};
var FxEase = {
In:function(fx,p,x){return fx(p,x,1);},
Out:function(fx,p,x){return 1-fx(1-p,x);},
InOut:function(fx,p,x){
var r=fxEaseInOutRatio&&fxEaseInOutRatio||2;
return (p<=0.5?fx(2*p,x):(2-fx(2*(1-p),x*r)))/2;}
};
var FxAnims = {"L":FxAnim.Linear,"P":FxAnim.Pow,"E":FxAnim.Expo,"B":FxAnim.Back};
var FxEases = {"In":FxEase.In,"Out":FxEase.Out,"InOut":FxEase.InOut};
var fctFxAnim = typeof fxAnim!='undefined'&&fxAnim!=null?FxAnims[fxAnim]:FxAnim.Pow;
var fxPowerVal = typeof fxPower!='undefined'?fxPower:null;
var fctFxEase = typeof fxEase!='undefined'&&fxEase!=null?FxEases[fxEase]:FxEase.InOut;
var fxEaseInOutRatio = typeof fxEaseRatio!='undefined'&&fxEaseRatio!=null?fxEaseRatio:null;
// ============================================================
// ============================================================
// Animate items!
var step = 0;
var animSteps2 = animSteps + totalAnimOffset;
if (animSteps2 < maxAnimSteps) {
animSteps2 = maxAnimSteps;
}
var animateItems = function() {
for(var idx=0;idx<items.length;idx++) {
var step2 = step - itemsAnimOffset[idx];
var animStepsItem = itemsFxSteps[idx] != null ? itemsFxSteps[idx] : animSteps;
if (step2>=0 && step2<=animStepsItem) {
var item = items[idx];
var stepBase = step2/animStepsItem;
if(item!=null) {
// Calculate new X position
if(itemsX1[idx]==null) { itemsX1[idx]=item.getPositionX(); }
if(itemsX2[idx]==null) { itemsX2[idx]=itemsX1[idx]; }
if(itemsDeltaX[idx]==null) { itemsDeltaX[idx]=itemsX1[idx]-itemsX2[idx]; }
var itemStepX = itemsX2[idx];
//if (itemsDeltaX[idx]!=0) {
var fctFxAnimX = itemsFxAnim[idx]==null||itemsFxAnim[idx]==fxAnim ? fctFxAnim : FxAnims[itemsFxAnim[idx]];
var fxPowerX = itemsFxPower[idx]==null||itemsFxPower[idx]==fxPowerVal ? fxPowerVal : itemsFxPower[idx];
var fctFxEaseX = itemsFxEase[idx]==null||itemsFxEase[idx]==fxEase ? fctFxEase : FxEases[itemsFxEase[idx]];
var stepFactorX = fctFxEaseX(fctFxAnimX,stepBase,fxPowerX);
itemStepX = Math.round(itemsX1[idx]-(stepFactorX*itemsDeltaX[idx]));
//}
// Calculate new Y position
if(itemsY1[idx]==null) { itemsY1[idx]=item.getPositionY(); }
if(itemsY2[idx]==null) { itemsY2[idx]=itemsY1[idx]; }
if(itemsDeltaY[idx]==null) { itemsDeltaY[idx]=itemsY1[idx]-itemsY2[idx]; }
var itemStepY = itemsY2[idx];
//if (itemsDeltaY[idx]!=0) {
var fctFxAnimY = itemsFxAnim2[idx]==null||itemsFxAnim2[idx]==fxAnim ? fctFxAnim : FxAnims[itemsFxAnim2[idx]];
var fxPowerY = itemsFxPower2[idx]==null||itemsFxPower2[idx]==fxPowerVal ? fxPowerVal : itemsFxPower2[idx];
var fctFxEaseY = itemsFxEase2[idx]==null||itemsFxEase2[idx]==fxEase ? fctFxEase : FxEases[itemsFxEase2[idx]];
var stepFactorY = fctFxEaseY(fctFxAnimY,stepBase,fxPowerY);
itemStepY = Math.round(itemsY1[idx]-(stepFactorY*itemsDeltaY[idx]));
//}
// Set position of item or scroll inside container
if (item.getType()=="Desktop" || item.getType()=="Container") {
item.setPosition(itemStepX,itemStepY,1,false);
} else {
item.setPosition(itemStepX,itemStepY);
}
if (step2==0 && itemsZ[idx]!=null) {
dt.setItemZIndex(itemIds[idx],itemsZ[idx]);
}
}
if(item!=null && itemsDeltaA[idx]!=0) {
// Calculate new alpha value
var itemStepA = itemsA2[idx];
var fctFxAnimA = FxAnim.Linear;
var fxPowerA = null;
var fctFxEaseA = FxEase.In;
var stepFactorA = fctFxEaseA(fctFxAnimA,stepBase,fxPowerA);
itemStepA = Math.round(itemsA1[idx]-(stepFactorA*itemsDeltaA[idx]));
item.getProperties().edit()
.setInteger("i.alpha",itemStepA)
.commit();
}
}
}
step++;
if (step<=animSteps2) {
setTimeout(animateItems,animDelay);
} else {
}
}
// ============================================================
// Let the show begin!
animateItems();
Android.makeNewToast("run", true).show()
//","flags":0,"id":49}
//Flags: app custom
//Name: [mates] Interpolacion Newbille
var p=[[]];
var f;
var xi;
var x;
var func=prompt("Introduce la función f en javascript, los puntos a usar en lista y el punto a evaluar",LL.getScriptTag()||"f=function(x){\n\n};\nxi=[];\nx=");
LL.setScriptTag(func);
eval(func);
var n=xi.length-1;
for(var i=0;i<=n;++i){
p[i]=[];
eval("p["+i+"][0]=function(x){return f(xi["+i+"]);};");
}
for(var k=1;k<=n;++k){
for(var i=0;i<=n-k;++i){
eval("p["+i+"]["+k+"]=function(x){\nreturn ("+(xi[i+k])+"-x)/"+(xi[i+k]-xi[i])+"*p["+i+"]["+(k-1)+"](x)+(x-("+(xi[i])+"))/"+(xi[i+k]-xi[i])+"*p["+(i+1)+"]["+(k-1)+"](x);\n};");
//alert(p[i][k](0.5));
}
}
alert(p[0][n](x));
//Flags: item
//Name: [old] animated icon
var fps=60;//frames per second
var useBackground=true;//set this to true to set the gif in the box background, otherwise the icon is used
var fix = false; //set this to true if you see no image
//classes
LL.bindClass("android.graphics.Movie");
if(fix){
LL.bindClass("java.io.FileInputStream");
LL.bindClass("java.io.ByteArrayOutputStream");
LL.bindClass("java.lang.Byte");
LL.bindClass("java.lang.reflect.Array");
}
//tags
var tagpath="anicon";
var tagid="aniconid";
//global vars
var thisscript=LL.getCurrentScript();
var item=null;
var source="";
//when used startActivityForResult
if(typeof resultCode!='undefined'){
if(!filechosen()) return;
}else{
//when launched from event
item=LL.getEvent().getItem();
source=LL.getEvent().getSource();
}
if(item==null) return;
if(source=="I_PAUSED"){
stop();
return;
}
//file
var path=item.getTag(tagpath);
if(path==null||source=="MENU_ITEM"){
choosefile();
return;
}
//start token
var gif;
if(fix){
//some android 4.x have problems with decodeFromPath
var array = streamToBytes( new FileInputStream(path) );
gif= Movie.decodeByteArray(array, 0, array.length); //gif movie
}else{
gif=Movie.decodeFile(path);//gif movie
}
if(gif == null){
if(confirm("The gif file couldn't be found. Did you removed it or renamed a parent folder?\n(saved path: '"+path+"')\n Do you want to choose another one?"))choosefile();
return;
}
var t=gif.duration()*Math.random();//the current time of the movie, random start
fps=1000/fps;
var size;
if(useBackground){
size=[item.getWidth(),item.getHeight()];
item.setBoxBackground(LL.createImage(size[0],size[1]),"n");
}else{
var im=item.getImage();
size=[im.getWidth(),im.getHeight()];//size of the live image
}
var oldid=item.getTag(tagid);
var id;
do{id=Math.random();}while(id==oldid);
item.setTag(tagid,id);//unique token
//item.getRootView().getChildAt(0).setLayerType(View.LAYER_TYPE_SOFTWARE,null);
//start of the animation loop
update();
function stop(){
item.setTag(tagid,"-1");//stop animation
}
function update(){
if(LL.isPaused()){
//launcher paused
stop();
return;
}
if(id!=item.getTag(tagid)){
//another instance of this script is fired
return;
}
//var nim=LL.createImage(size[0],size[1]);
var nim=useBackground?item.getBoxBackground("n"):item.getImage();
if(nim==null){stop();return;}
var nc=nim.draw();
nc.drawColor(0);
nc.scale(nim.getWidth()/gif.width(),nim.getHeight()/gif.height());
gif.setTime(t)
gif.draw(nc,0,0);//draws the corresponding image
nim.update();
/*try{
item.setImage(nim);
}catch(e){
stop();//item not found, deleted?
}*/
t=(t+fps)%gif.duration();
setTimeout(update,fps);//repeat
}
function choosefile(){
//using Lightning file picker because android one on latest android versions return 'content://...' that can change when restarting phone
var intent =new Intent();
intent.setComponent(ComponentName.unflattenFromString("net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.FilePicker"));//file picker activity
intent['putExtra(java.lang.String,java.lang.String[])']("e",["gif"]);//list of extensions to show
if(thisscript.getTag()!=null)intent.putExtra("p",thisscript.getTag());//path where to start
LL.startActivityForResult(intent,thisscript,item.getId());
}
function filechosen(){
if(data==null){
Android.makeNewToast("Cancelled",true).show();
return false
}
var dp=data.getExtra("p");//last path opened
var df=data.getExtra("f");//file chosen
if(dp!=null)thisscript.setTag(data.getExtra("p"));//so next time it will open in the previous path
if(df==null){
Android.makeNewToast("No file picked",true).show();
return false
}
//otherwise gif chosen
item=LL.getItemById(token);
item.setTag(tagpath,df);//saved path
if(useBackground)item.setCustomIcon(LL.createImage(df));//this makes the item to have a custom icon related to the animated one
if(confirm("Do you want it to be automatically animated?\n(script in the resumed/paused event)")){
//it make this for you
item.getProperties().edit()
.setEventHandler("i.resumed",EventHandler.RUN_SCRIPT,thisscript.getId())
.setEventHandler("i.paused",EventHandler.RUN_SCRIPT, thisscript.getId())
.commit();
}
return true;
}
function streamToBytes(is) {
var os = new ByteArrayOutputStream(1024);
var buffer =Array.newInstance(Byte.TYPE,1024);
var len;
try {
while ((len = is.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (e) {
alert(e);
}
return os.toByteArray();
}
//Flags: item
//Name: [old] html labels
LL.bindClass("android.text.Html");
LL.bindClass("android.view.ViewGroup");
var item=LL.getEvent().getItem();
if(!findTextView(item.getRootView())){
Android.makeNewToast("Label's TextView of the item "+item+" couldn't be found",false).show();
}
function findTextView(v){
if(v.class.toString()=="class net.pierrox.lightning_launcher.views.aq"){
v.setText(Html.fromHtml(item.getLabel()));
return true;
}
if(v instanceof ViewGroup){
var count=v.getChildCount();
for(var t=0;t<count;++t){
if(findTextView(v.getChildAt(t)))return true;
}
}
return false;
}
//Flags:
//Name: [oreofix] package intents
//receiver as defined in Lightning's manifest
bindClass("net.pierrox.lightning_launcher.util.MPReceiver");
//global vars
var cntx = getEvent().getScreen().getContext();//LL.getContext();
var pm = cntx.getPackageManager();
var mpr = new MPReceiver();
var script = getCurrentScript();
//get latest id tried
var id = script.getTag() || 0;
//if previous (last tried) is null, reset. Probably due to device restart
if(id!=0 && pm.getChangedPackages(id-1)==null){
id=0;
}
//get the list
var packages = pm.getChangedPackages(id);
//no list, no changes
if(packages==null){
return;
}
//get packages and save new id
var list=packages.getPackageNames();
script.setTag(packages.getSequenceNumber());
//for each package...
for(var t=0;t<list.size();t++){
var name = list.get(t);
//if no error, package exist, send 'replaced' (LL checks if it is not existent so 'added' is not necessary. Thanks Pierre!)
var action = "android.intent.action.PACKAGE_REPLACED";
try {
pm.getPackageInfo(name,pm.GET_META_DATA);
} catch (e) {
//if error, package doesn't exist, send 'removed'
action = "android.intent.action.PACKAGE_REMOVED";
}
//create Intent and send to LL
var intent = new Intent();
intent.setData(Uri.parse(name));
intent.setAction(action);
mpr.onReceive(cntx,intent);
}
//Flags: item
//Name: [personal wiki]portapapeles
var textColor=0xffffffff;//the color of the text from the textbox
//tag
var tag="clipboard";
var tagold="clipboardOld";
//classes
LL.bindClass("android.widget.EditText");
LL.bindClass("android.content.ClipData");
//vars
var cntx=LL.getContext();
var clipboard = cntx.getSystemService(cntx.CLIPBOARD_SERVICE);
//get clipboard text
var cText=getCText();
//more vars
var source=LL.getEvent().getSource();
var it=LL.getEvent().getItem();
var itv=it.getView();
var vText=getVText(itv);
//what to do
switch(source){
case "I_RESUMED":
//sets the clipboard text in the textbox
setVText(itv,cText);
it.setTag(tag,cText);
if(vText!=cText) it.setTag(tagold,vText);
break;
case "I_PAUSED":
//if the clipboard didn't changed, sets the textbox text into the clipboard
if(it.getTag(tag)==cText&&cText!=vText)setCText(vText);
it.setTag(tag,cText);
break;
case "I_LONG_CLICK":
//sends the text if not null
if(vText!=null)sendText(vText);
break;
default:
alert(LL.getEvent().getSource());
break;
}
//sets the text of the v view to t (if not null)
function setVText(v,t){
if(t==null){
v.setText(null);
v.setHint("Clipboard contains no text");
//v.setFocusable(false);
v.setFocusableInTouchMode(true);
}else{
v.setText(t);
v.setHint("");
v.setFocusableInTouchMode(true);
}
}
//returns the text of the view v
function getVText(v){
var t=v.getText();
return t;
}
//returns the text of the clipboard if it is text, otherwise returns null
function getCText(){
if(!clipboard.hasPrimaryClip() || clipboard.getPrimaryClip() == null) return null
if(!clipboard.getPrimaryClipDescription().hasMimeType("text/*"))return null;
var t= clipboard.getPrimaryClip().getItemAt(0).getText();
return t;
}
//sets 'text' as the clipboard text (with a custom description)
function setCText(text){
var clip = ClipData.newPlainText("LL clipboard editor",text);//custom description, remove if necessary
clipboard.setPrimaryClip(clip);
}
//sends the text
function sendText(text){
var sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent["putExtra(java.lang.String,java.lang.String)"](Intent.EXTRA_TEXT, text);
sendIntent.setType("text/plain");
LL.startActivity(Intent.createChooser(sendIntent, "Send text to:"));
}
//Flags:
//Name: [personal wiki]portapapeles create
var textColor=0xffffffff;//the color of the text from the textbox
//tag
var tag="clipboard";
//classes
LL.bindClass("android.widget.EditText");
LL.bindClass("android.content.ClipData");
//vars
var cntx=LL.getContext();
var clipboard = cntx.getSystemService(cntx.CLIPBOARD_SERVICE);
//get clipboard text
var cText=getCText();
//alert(LL.getEvent().getSource());
//is the script run from the create event of a custom view?
item.setVerticalGrab(true);
var v=new EditText(cntx);
v.setTextColor(textColor);
v.setGravity(80);//bottom
setVText(v,cText);
item.setTag(tag,cText);
return v;
//sets the text of the v view to t (if not null)
function setVText(v,t){
if(t==null){
v.setText(null);
v.setHint("Clipboard contains no text");
v.setFocusable(false);
}else{
v.setText(t);
v.setHint("");
v.setFocusableInTouchMode(true);
}
}
//returns the text of the view v
function getVText(v){
var t=v.getText();
return t;
}
//returns the text of the clipboard if it is text, otherwise returns null
function getCText(){
if(!clipboard.hasPrimaryClip()) return null
if(!clipboard.getPrimaryClipDescription().hasMimeType("text/*"))return null;
var t= clipboard.getPrimaryClip().getItemAt(0).getText();
return t;
}
//sets 'text' as the clipboard text (with a custom description)
function setCText(text){
var clip = ClipData.newPlainText("LL clipboard editor",text);//custom description, remove if necessary
clipboard.setPrimaryClip(clip);
}
//Flags:
//Name: [personal wiki]portapapeles menu
// it is possible to read the current menu mode and configure it accordingly
if(menu.getMode() == Menu.MODE_ITEM_NO_EM) {
menu.getMainItemsView().removeAllViews();
//send item
var text = item.getView().getText();
if(text!=null && text!=""){
menu.addMainItem("Send...", send);
menu.addMainItem("Notification",notification);
}
//restore
menu.addMainItem("Restore",restore);
//clear
menu.addMainItem("Clear",clear);
}
// function to execute when a menu item is clicked
function send(v) {
menu.close();
var text = item.getView().getText();
//sends the text
var sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent["putExtra(java.lang.String,java.lang.String)"](Intent.EXTRA_TEXT, text);
sendIntent.setType("text/plain");
LL.startActivity(Intent.createChooser(sendIntent, "Send text to:"));
}//end send
function notification(v){
menu.close();
//bind classes
LL.bindClass("android.app.Notification");
LL.bindClass("android.app.NotificationManager");
LL.bindClass("android.content.Context");
LL.bindClass("android.R");
LL.bindClass("android.app.PendingIntent");
//vars used also in the returned functions
var cntx=LL.getContext();//if you need a 'context' for a java function, this is probably what you need.
var nm=cntx.getSystemService(Context.NOTIFICATION_SERVICE);//returns the service used to work with notifications
var text = item.getView().getText()+"";
if(text==null) return;
var pos=text.indexOf("\n");
lines = pos==-1 ? [text,null] : [ text.substring(0,pos), text.substring(pos+1)];
if(lines[0].length>50){
lines=[null,lines[1]==null?lines[0]:lines[0]+"\n"+lines[1]];
}
var intent=new Intent().getIntent("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.Dashboard;i.a=35;end")//'launch a script' shortcut
intent.putExtra('d',0x20+'/ cntx.getSystemService(cntx.CLIPBOARD_SERVICE).setPrimaryClip(ClipData.newPlainText("LL clipboard editor",JSON.parse('+JSON.stringify(JSON.stringify(text))+')));');//which script and data
//create the notification from a builder
var n=Notification.Builder(cntx,"script")//start the builder
.setContentTitle(lines[0])//title
.setContentText(lines[1])//main text
.setStyle(new Notification.BigTextStyle())
.setContentInfo("portapapeles LL")//information
.setSmallIcon(R.drawable.ic_dialog_info)//small icon
.setSubText("portapapeles")//secondary text
.setAutoCancel(false)//set to true to cancel when clicking
.setOngoing(false)
.setContentIntent(PendingIntent.getActivity(cntx,
nm.getActiveNotifications().length,intent,0x8000000))
.build();//finish the builder and returns a ready notification
nm.notify(
nm.getActiveNotifications().length,n);//show the notification. If you want to show more than one you need to set a different first number for each
}
function restore(v){
var old=item.getView().getText();
item.getView().setText(item.getTag("clipboardOld"));
item.setTag("clipboardOld",old);
}
function clear(v){
menu.close();
var old=item.getView().getText();
item.getView().setText("");
item.setTag("clipboardOld",old);
}
//Flags:
//Name: [personal] app drawer folders
var event = LL.getEvent();
var fold = event.getContainer();
var source = event.getSource();
var original=LL.getContainerById(99).getItemByName("iconos");;
if(source=="C_RESUMED"){
var items=fold.getItems();
var list=[];
for(var t=items.getLength()-1;t>=0;){
var item=items.getAt(t);
//if(item.getLabel()=="DummyScript")continue;
list[t--]=item;
};
list.sort(function(a,b){return a.getLabel().toLowerCase()<b.getLabel().toLowerCase()?1:-1;});
var h=0,v=0;
for(var t=list.length-1;t>=0;--t){
list[t].setCell(h,v,h+1,v+1,true);
h++;
if(h>=6){v++;h=0};
}
/*
if(list.length<=6*4){
var dummy=c.getItemByLabel("dummyForScript")||c.creat
}
*/
fold.setPosition(0,0,1,false);
var op=fold.getOpener();
if(op!=null &&op.getParent().getId()==99){
op.setImage(original.getDefaultIcon());
op.setBoxBackground(original.getBoxBackground("s"),"n");
}
}//endif resumed
if(source=="C_PAUSED"){
//change to setCustomIcon() to set it
var op=fold.getOpener();
if(op!=null&&op.getParent().getId()==99){
op.setImage(original.getCustomIcon());
op.setBoxBackground(original.getBoxBackground("n"),"n");
}
}//endif paused
//Flags: app item
//Name: [personal] Boing
var bounciness = 0.99;//Reduction every tick, between 0 (only one tick) and 1 (always bouncing) [Recommended 0.95]
var inVel = 0 //initial velocity. set it to 0 for random one [recommended 0.5]
var frecuency = 60;//ticks per second [Recommended 60]
var event = LL.getEvent();
var cont = event.getContainer();
var clicked = event.getItem();
if(clicked!=null){;
run(clicked);
}else{
inVel=prompt("This will bounce all items in the container\nAre you sure?\n(velocity,0=random)",inVel)
if(inVel==null)return;
var items=cont.getItems();
for(var i=items.getLength()-1; i>=0;--i){
var item=items.getAt(i);
if(item.getType()!="StopPoint")run(item);
}
}
function run(item){
var ang = Math.random()*2*Math.PI;
var invel=inVel; if(invel<=0)invel=Math.random()/4;
invel*=(cont.getHeight()+cont.getWidth())/2;
var vel = [ Math.cos(ang)*invel , Math.sin(ang)*invel ];
var size = [ item.getWidth()*item.getScaleX() , item.getHeight()*item.getScaleY() ];
var token=Math.random();
item.setTag("boing",token);
tick(item,vel,size,token);
}
function tick(item,vel,size,token){
//exit statement
if((Math.abs(vel[0])<1 && Math.abs(vel[1])<1)||LL.isPaused()||item.getTag("boing")!=token)return;
//Reduction
vel=[ vel[0]*bounciness , vel[1]*bounciness ];
var newpos = [ item.getPositionX()+vel[0] , item.getPositionY()+vel[1] ];
var t;
//right
t=(newpos[0]+size[0])-( cont.getPositionX()+cont.getWidth()/cont.getPositionScale() ) ;
if(t>0){newpos[0]-=2*t;vel[0]=-vel[0];}
//bottom
t=(newpos[1]+size[1])-( cont.getPositionY()+cont.getHeight()/cont.getPositionScale() ) ;
if(t>0){newpos[1]-=2*t;vel[1]=-vel[1];}
//left
t= newpos[0]- cont.getPositionX();
if(t<0){newpos[0]-=2*t;vel[0]=-vel[0];}
//top
t= newpos[1]- cont.getPositionY();
if(t<0){newpos[1]-=2*t;vel[1]=-vel[1];}
//set and repeat
item.setPosition(newpos[0] , newpos[1] );
setTimeout(function(){tick(item,vel,size,token);},1000/frecuency);
}
//Flags: app
//Name: [personal] Compare folders
var from = LL.getContainerById( 0x7f ).getItems();
var to_c = LL.getContainerById( 0x6e );
var to = to_c.getItems();
var notfoundgeneral = true;
for(var i=from.getLength()-1;i>=0;--i){
var ee=from.getAt(i);
var e = ee.getLabel();
if(e=="non")continue;
var notfound = true;
for(var j=to.getLength()-1;j>=0;--j){
if(e==to.getAt(j).getLabel()){
notfound=false;
continue;
}
}
if(notfound){
//alert("Missing game: "+ e);
//add to the folder
to_c.addShortcut(e,ee.getIntent(),Math.random()*to_c.getWidth(),Math.random()*to_c.getHeight()).setDefaultIcon(ee.getDefaultIcon());
Android.makeNewToast("Added game: "+e,true).show();
//----
notfoundgeneral=false;
}
}
//if(notfoundgeneral)Android.makeNewToast("Games compared. All ok",true).show();
//Flags: custom
//Name: [personal] Cyclic label
//the item
var it=LL.getEvent().getItem();
//the saved index, 0 if not found
var ind=parseInt(it.getTag()||"0");
//the list of sublabels
var list=it.getLabel().split("\n\n");
//get the sublabel to show
var l=list[ind];
//save the next index
it.setTag( (ind+1)%list.length );
//the number of characters shown
var index=0;
//start the sideshow
setTimeout(tick,250);
function tick(){
//the first characters are shown normally
//the rest that are not line breaks/spaces are replaced with my old friend the 'no break space'
it.setLabel(
l.substring(0,index)
+l.substring(index,l.length).replace( /[^\n\r\s]/g , String.fromCharCode(0xA0) )
);
//update the index and, if there are still characters and the launcher is active, continue the sideshow
index+=2;
if(index<=l.length+1&&!LL.isPaused())
setTimeout(tick,0);
}
//Flags: item
//Name: [personal] Games
//vars
var item=LL.getEvent().getItem();
var cont=LL.getEvent().getContainer();
var script=LL.getCurrentScript();
var tag="gamestag";
var prev=script.getTag(tag)||"";
var random = prev;
while(random==prev)random=Math.random();
script.setTag(tag,random);
//change scale
var items = cont.getItems();
var h=0,v=0;
for(var j=0;j<items.getLength();++j){
var ite=items.getAt(j);
if(ite.getType()!="Shortcut")continue;
ite.setSize(125,125);//hardcoded
/*
if(ite.getRotation()==0){ite.setSize(98,143);}else{ite.setSize(143,98);}
ite.setScale(1,1);
ite.setPosition(h*98,v*142);
++h;
if(h>6){h=0;++v;}
*/
var mult=0.99;
if(item.getLabel()==ite.getLabel())mult=1.2;
var sca=ite.getScaleX()*mult;
sca=sca>1.5?1.5:sca<0.6?0.6:sca;
ite.setScale(sca,sca);
}
//zoom in
/*
var siz = [ item.getWidth()*item.getScaleX(),item.getHeight()*item.getScaleY() ]
if(item.getRotation()!=0){siz[2]=siz[0];siz[0]=siz[1];siz[1]=siz[2];}
var scale = Math.min( cont.getWidth()/siz[0] , cont.getHeight()/siz[1] );
var pos = [ item.getPositionX()-(cont.getWidth()/scale-siz[0])/2 , item.getPositionY()-(cont.getHeight()/scale-siz[1])/2 ]
cont.setPosition(pos[0],pos[1],scale,true);
*/
//new
var c=[];
var d=[item.getRotation()*Math.PI/180,item.getWidth()*item.getScaleX(),item.getHeight()*item.getScaleY()]; c[0]=Math.abs(d[2]*Math.sin(d[0]))+Math.abs(d[1]*Math.cos(d[0]));
c[1]=Math.abs(d[1]*Math.sin(d[0]))+Math.abs(d[2]*Math.cos(d[0]));
var scale = Math.min( cont.getWidth()/c[0] , cont.getHeight()/c[1] );
var pos = [ item.getPositionX()-(cont.getWidth()/scale-c[0])/2 , item.getPositionY()-(cont.getHeight()/scale-c[1])/2 ]
cont.setPosition(pos[0],pos[1],scale,true);
setTimeout(function(){
//launch
item.launch();
/*
var t=0;
while((!LL.isPaused()) &&t<100000)t=t+1;
Android.makeNewToast(t+"_"+LL.isPaused()+"_",true).show();
*/
setTimeout(function(){
//check rotation
if(LL.isPaused() && script.getTag(tag)==random){
//item.getParent().getOpener().close()
cont.getOpener().close();
//Android.makeNewToast("closed",false).show();
//zoom out
cont.setPosition(0,0,1,false);
if(item.getTag()=="No rotate") return;
var desk = LL.getCurrentDesktop();
var newrot = desk.getHeight()>desk.getWidth();
var oldrot = item.getRotation()
if(!newrot&&oldrot==0){
Android.makeNewToast("Changed to "+ (newrot?"Portrait":"Landscape"),true).show();
item.setRotation( newrot?0:90);
}
//Android.makeNewToast(desk.getHeight()+" "+desk.getWidth(),false).show();
}
},4000);//after launch
},300);//before launch
//Flags: item
//Name: [personal] Inline app drawer configuration
// sets all folders of this container to have their bottom position at a specific coordinate
// BUG: folders are not closed
var BOTTOM_POS = 1775;
var time=200;
function defer(f,p){
setTimeout(function(){f(p)},time+=500);
}
var items = getEvent().getContainer().getItems();
for(var t=0;t<items.getLength();++t){
var i = items.getAt(t);
var c = i.getContainer();
defer(function(i){
i.open();
},i);
defer(function([i,c]){
i.getProperties()
.edit()
.setInteger("f.wY",BOTTOM_POS-c.getHeight())
.commit();
},[i,c]);
defer(function(i){
i.close();
},i);
}
/*setTimeout(function(){
getEvent().getScreen()
.runAction(EventHandler.CLOSE_ALL_FOLDERS)
},500);*/
//Flags: item
//Name: [personal] Launch as new
var i=LL.getEvent().getItem();
var nt= i.getIntent();
LL.startActivity( nt.clone().addFlags( Intent().FLAG_ACTIVITY_CLEAR_TASK ));
/*
i.setIntent(nt.clone().addFlags( Intent().FLAG_ACTIVITY_CLEAR_TASK ));
i.launch();
i.setIntent(nt);
//FLAG_ACTIVITY_CLEAR_TASK
*/
//Flags:
//Name: [personal] Main desktop
var c = getEvent().getContainer();
var p = c.getPositionX();
var w = c.getWidth();
c.getItemByName("usage").setPosition(
p > w ? -w : p > 0 ? 0 : p
,0)
//Flags:
//Name: [personal] material scrolling
var cont=LL.getEvent().getContainer();
if(cont.getWidth()==0) return;
if(cont.getType()=="Desktop"){
var it=cont.getItemByLabel("parallax");
//145
var panelW=551;//-cont.getItemByName("Panel").getPositionX();//hard set
//click
if(LL.getEvent().getSource()=="SHORTCUT"){
cont.setPosition(cont.getPositionX()==0?-panelW:0,cont.getPositionY(),1,true);
return;
}
//lateral bar
//dim background
if(cont.getPositionX()==0){
it.setSize(1,it.getHeight());
}else{
it.setSize(cont.getWidth()+1,it.getHeight());
it.getProperties().edit().setInteger("i.alpha",-cont.getPositionX()/cont.getWidth()*255).commit();
}
/*it.setPosition(-cont.getPositionX()-it.getWidth(),it.getPositionY());*/
indicator();
}else{
var it1=cont.getItemByName("indicator1");
var it2=cont.getItemByName("indicator2");
//horizontal indicator
var p=cont.getPositionX()/cont.getWidth();
//horizontal indicators
it1.setPosition(cont.getWidth()/3*(p+1),it1.getPositionY());
it2.setPosition(cont.getWidth()/3*(
p<=-1? p+4 :
p>=1 ? p-2 :
p+1
),it2.getPositionY());
//labels
var mins=0.6
function setit(name,page){
var c=Math.exp(-Math.min(Math.abs(p-page),Math.abs(p+3-page),Math.abs(p-3-page)));
c=c<mins?mins:c;
cont.getItemByName(name).setScale(c,c);
}
setit("left",-1)
setit("middle",0);
setit("right",1);
//reset subpanels
if(cont.getPositionX()==0&&cont.getPositionScale()==1)setTimeout(function(){ cont.getItemByName("bar").launch();},0);
return
//warp
if(p>=2)cont.setPosition((p-3)*cont.getWidth(),cont.getPositionY(),1,false);
else if(p<=-2)cont.setPosition((p+3)*cont.getWidth(),cont.getPositionY(),1,false);
}
function indicator(){
//script by Ren Shore
var item = cont.getItemByName("indicator")
img=LL.createImage(100,100);
//item.setImage(img);
canvas = img.draw();
var x=cont.getPositionX();
var p = new Paint();
p.setAntiAlias(true);
p.setStrokeWidth(4);
p.setColor(0xffffffff);
var canvas = img.draw();
var rot=x<0?(-x*180/(panelW))+180:180;
if(item.getTag("arrow")==null)rot=-rot;
if(x>=0)item.setTag("arrow","-");
if(x<=-panelW)item.setTag("arrow",null);
//item.setRotation(0);
var lines=
[
[
[ 30,39,70,39 ],//before
[ 33,51,53,33 ]//after
],
[
[ 30,50,70,50 ],
[ 33,50,70,50 ]
],
[
[ 30,61,70,61 ],
[ 33,49,53,69 ]
]
];
canvas.rotate(rot,50,50);
for(i=0;i<lines.length;i++){
var A=[0,0,0,0];
for(j=0;j<=3;j++){
a=lines[i][0][j];
b=lines[i][1][j];
A[j]=x>=0?a:a+((b-a)*(-x/panelW));
}
canvas.drawLine(A[0],A[1],A[2],A[3],p);
}
//img.update();
item.setImage(img);
}
//Flags: app item
//Name: [personal] material top indicator
//Indicators by +TrianguloY
/*Reminder:
the items need to be labeled "indicator 0" "indicator 1" "indicator 2" ...
Unzoom (or zoom) to move all indicators to their original positions, then you can edit easily.
Running the script in the container (save all) or item (save that item) to force a save of the position of the indicator. Use this after modifying manually one. (not necessary with newly created ones)
Set the AUTOREFRESH to true if you have a lot of indicators and it lags a bit. Keep in mind you will need to unzoom/force a save/restart the launcher to apply new changes
*/
var AUTOREFRESH = true;
var ev=LL.getEvent();
var cont=ev.getContainer();
var cy=cont.getPositionY();
//flags
var inactive=cont.getPositionScale()!=1;//to disable when zoom
var reset=ev.getSource()!="C_POSITION_CHANGED";//to reset at desired
var resetid=-1;
if(reset&&ev.getItem()!=null){resetid=ev.getItem().getId();reset=false;}
if(AUTOREFRESH||reset||resetid!=-1||!("indicator_items" in this)){
//create the array of indicators (indicator_items)
indicator_items=[];
var l=0;
while(true){
var p=cont.getItemByName("indicator "+l);
if(p==null)break;
indicator_items[l++]=p;
}
}
//asignating position
var last=Math.infinity;
for(var t=indicator_items.length-1;t>=0;--t){
var item=indicator_items[t];
var iy=getiy(item);
var ny;
if((cy<=iy&&t!=0)||inactive||reset){
//set the item in their position
ny=iy;
}else{
//set the item above the previous one
var o=item.getHeight()-last;
ny=cy-(o>0?o:0);
}
//set and save
item.setPosition(item.getPositionX(),ny);
last=ny-cy;
}
function getiy(item){
//get the saved tag, otherwise, prepare the item;
var d=item.getTag("indicator");
if(d!=null && !reset && resetid!=item.getId())return parseInt(d);
//if no tag found or reset active
d=item.getPositionY();
item.setTag("indicator",d);
item.getProperties().edit().setBoolean("i.onGrid",false).commit();//properties set
return d;
}
//Flags:
//Name: [personal] random app
var cont = LL.getContainerById(99);
var c=0;
var act=LL.getEvent().getItem();
var folder = null;
do{
c++;
var a=cont.getItems();
if(a.getLength()==0){
cont=cont.getParent();
}else{
item=a.getAt( Math.floor(Math.random()*a.getLength()) );
if(item.getType()=="Folder"){
folder=item;
cont=item.getContainer();
}else if(item.getType()!="Shortcut"){
//alert("What's this?! "+item.getType() );
//return;
}else{
/*Change this if you want*/
/*
var str = item.getLabel()+".apk";
while(cont.getId()!=99){
str=cont.getOpener().getLabel()+"/"+str;
cont=cont.getParent();
}
str="D://"+str;
if(!confirm("Launch?\n"+str ) )return;
if( folder!=null){
folder.close();
}
try{
item.launch();
}catch(err){
item.setCell(item.getCell().getLeft(),item.getCell().getTop(),item.getCell().getRight(),item.getCell().getBottom());
item.launch();
}*/
act.setCustomIcon(item.getDefaultIcon());
act.setLabel(item.getLabel());
act.setIntent(item.getIntent());
return;
}
}
}while(cont!=null && c<100);
alert("Warning: avoid empty containers.");
//Flags:
//Name: [personal] random color background
if(LL.isPaused())return;
var rand=(parseFloat(LL.getScriptTag()||"0")+90+Math.random()*180)%360;
LL.setScriptTag(rand);
var c=LL.getEvent().getContainer();
//alert(c)
setbg(c.getItemByName("bar"),rc(255/2,rand));
setbg(c.getItemByName("background"),rc(255/8,rand));
function rc(a,h){
return Color.HSVToColor(a,[h,1,1]);
}
function setbg(it,c){
var p=it.getProperties().edit()
p.getBox("i.box").setColor("c","n",c);
p.commit();
}
//Flags:
//Name: [personal] relative bookmark
var v=JSON.parse(LL.getEvent().getData());
var c=LL.getEvent().getContainer();
c.setPosition(v[0]!=null?v[0]*c.getWidth():c.getPositionX(),v[1]!=null?v[1]*c.getHeight():c.getPositionY(),c.getPositionScale(),v[2]!=null?v[2]:true);
//Flags: custom
//Name: [personal] Reset all subcontainers
if(LL.getEvent().getSource()=="MENU_CUSTOM"){
if(LL.getScriptTag()!=null){
LL.setScriptTag(null);
Android.makeNewToast("Auto-reset enabled",true).show();
}else{
LL.setScriptTag("-");
Android.makeNewToast("Auto-reset disabled",true).show();
}
}
if(LL.getScriptTag()!=null)return;
var
flag=LL.getEvent().getData()!=null&&LL.getEvent().getData()!="";
var desk=flag?LL.getCurrentDesktop():LL.getEvent().getContainer();
if(desk==null||desk.getId()==-1)desk=LL.getCurrentDesktop();
setTimeout(function(){reset(desk);},0);
function reset(cont){
cont.setPosition(0,0,1,flag);
var a=cont.getItems();
for(var i=a.getLength()-1;i>=0;--i){
var aa=a.getAt(i);
if(aa.getType()=="Panel")reset(aa.getContainer());
}
}
/*LL.getContainerById(0).setPosition(0,0,1,true);
LL.getContainerById(119).setPosition(0,0,1,true);
LL.getContainerById(120).setPosition(0,0,1,true);
*/
//Flags: app item custom
//Name: [Personal] Save and restore positions
var velocity = 0.2;//The bigger, the faster (between (0,1] )
var frecuency = 60;//ticks per second [Recommended 60]
var cont = LL.getEvent().getContainer(); //The container
var tag = cont.getTag();
if(tag!=undefined){
//With data, hope it is from this script
var data=JSON.parse(tag);
if(confirm("Restore?")){
for(var i=data.ids.length-1;i>=0;--i){
var item= LL.getItemById(data.ids[i]);
item.setTag("boing",null);
//move the item to their position
if(item!=null){
var cen=center(item,false);
move( item , data.posX[i]-cen[0] , data.posY[i]-cen[1]);
}
}
cont.setPosition(0,0,1,true);//can be omitted
return;
}
}
if(!confirm("Save?"))return;
//save process
var data=new Object();
data.ids=[];
data.posX=[];
data.posY=[];
var items = cont.getItems();
for(var i=items.getLength()-1;i>=0;--i){
//save the data of each item
var t = items.getAt(i);
var cen=center(t,true);
data.posX[i]=cen[0]; t.getPositionX();
data.posY[i]=cen[1];
data.ids[i]=t.getId();
};
//final save
cont.setTag(JSON.stringify(data));
Android.makeNewToast("Saved "+data.ids.length+" item's position",true).show();
//custom lerp. It moves the item a bit and repeat
function move(item,posx,posy){
var xx=posx-item.getPositionX();
var yy=posy-item.getPositionY();
if( (Math.abs(xx)<1 && Math.abs(yy)<1) || LL.isPaused() ){
item.setPosition(posx,posy);
return;
}
xx*=velocity;
yy*=velocity;
item.setPosition( item.getPositionX()+xx , item.getPositionY()+yy );
setTimeout(function(){move(item,posx,posy);},1000/frecuency);
}
//custom function to get the center of the item
function center(item,absolute)
{
var r=item.getRotation()*Math.PI/180;
var sin=Math.abs(Math.sin(r));
var cos=Math.abs(Math.cos(r));
var w=item.getWidth()*item.getScaleX();
var h=item.getHeight()*item.getScaleY();
var x=(w*cos+h*sin)*0.5;
var y=(h*cos+w*sin)*0.5;
if(absolute){
x+=item.getPositionX();
y+=item.getPositionY();
}
return [x,y];
}
//Flags: app
//Name: [personal] widgets columns
//custom vars
var topmargin=100;
var rightmargin=150;
var bottommargin=0;
var leftmargin=0;
var velocity=0.5;
var frecuency=0;
//universal vars
var event=LL.getEvent();
var cont=event.getContainer();
//data computation
var colum= parseInt(cont.getTag("columns")||"2");
var data=LL.getEvent().getData();
if(data==null){
var saved=cont.getTag("columns_prev");
if(saved!=null){
cont.setBoundingBox(new RectL(0,0,cont.getWidth(),parseInt(saved)));
return;
}
}else if(data=="unzoom")colum+=1;
else if(data=="zoom")colum=colum>1?colum-1:1;
else colum=parseInt(data)>0?parseInt(data):colum;
cont.setTag("columns",colum);
//script vars
var used=[];
for(var t=0;t<=colum;++t)used[t]=topmargin;
var items=cont.getItems();
var width=(cont.getWidth()-rightmargin-leftmargin)/(colum==0?1:colum);
var prebottom=cont.getBoundingBox().getBottom()-cont.getHeight();
prebottom=prebottom<=0?0:cont.getPositionY()/prebottom;
if(prebottom>1)prebottom=1;
//for each item
for(var t=0;t<items.getLength();++t){
//only widgets, can be changed
var item=items.getAt(t);
if(item.getType()!="Widget") continue;
//scale computation
var size=[item.getWidth(),item.getHeight()];
var scale=(colum==0)?1:(width/size[0]);
var c=minVal(used);
//set new position/scale
move(item,[0,leftmargin+c*width,used[c],scale,scale]);
used[c]+=size[1]*scale;
}
//set screen position
var newbottom=used[maxVal(used)]+bottommargin;
var pos=prebottom*(newbottom-cont.getHeight());
cont.setPosition(0,pos>=0?pos:0,1,true);
//at last!
cont.setBoundingBox(new RectL(0,0,cont.getWidth(),Math.max(newbottom,cont.getHeight())));
//save for the update run
cont.setTag("columns_prev",newbottom);
/// functions ///
//returns the index of the minimum/maximum value of the array a
function minVal(a){
var m=0;
for(var t=0;t<colum;++t)if(a[t]<a[m])m=t;
return m;
}
function maxVal(a){
var m=0;
for(var t=0;t<colum;++t)if(a[t]>a[m])m=t;
return m;
}
//custom lerp. It moves the item a bit and repeat, stops when finish, when LL is not active or when another instance of the script runs
function move(item,dat){
//another script is running
if( colum!=cont.getTag("columns")){return;}
//actual data
var now = [
0,
item.getPositionX(),
item.getPositionY(),
item.getScaleX(),
item.getScaleY()
];
//calculate the next step
var cut=[0,0.5,0.5,0.01,0.01];
var step = [];
var flag = "";
for(var j=dat.length-1;j>0;--j){
step[j]=dat[j]-now[j];
if(Math.abs(step[j])>cut[j]){
flag+=j;
if (cut[j]==1){
step[j]=now[j]+(step[j]>0?Math.max(step[j]*velocity,cut[j]):Math.min(step[j]*velocity,-cut[j]));
}else step[j]=now[j]+step[j]*velocity;
}else step[j]=dat[j];
}
//if nothing changed or LL paused
if( flag=="" || LL.isPaused()){
item.setScale(dat[3],dat[4]);
item.setPosition(dat[1],dat[2]);
return;
}
//sets the next step and repeat
item.setScale(step[3],step[4]);
//var s=center(dat);
item.setPosition(step[1],step[2]);
velocity=(1+999*velocity)/1000;
setTimeout(function(){ move(item,dat);},frecuency==0?0:1000/frecuency);
}
//Flags:
//Name: [personal]Random Game
var items = LL.getEvent().getItem().getContainer().getItems();
var sel;
do{
sel=items.getAt(Math.floor(Math.random()*items.getLength()));
}while(sel.getType()!="Shortcut");
Android.makeNewToast(sel.getLabel(),true).show();
sel.launch();
//Flags: item
//Name: [pierre] draw on item
var x = event.getX();
var y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
prev_x = x;
prev_y = y;
hue = 0;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(5);
paint.setStrokeJoin(Paint.Join.ROUND);
image = item.getBoxBackground("n");
if(image == null) {
image = LL.createImage(512, 512);
item.setBoxBackground(image, "n",true);
}
canvas = image.draw();
canvas.scale( image.getWidth() / item.getWidth(), image.getHeight() / item.getHeight());
canvas.drawARGB(255,255,255,255);
break;
case MotionEvent.ACTION_MOVE:
hue += 10;
hue = hue % 360;
var c = Color.HSVToColor([hue, 1, 1]);
paint.setColor(c);
canvas.drawLine(prev_x, prev_y, x, y, paint);
prev_x = x;
prev_y = y;
image.update();
break;
case MotionEvent.ACTION_UP:
image.save();
paint = null;
canvas = null;
break;
}
return true;
//Flags: custom
//Name: [smallScript] WhatsApp finder
LL.startActivity(Intent.parseUri("whatsapp://send/?phone="+prompt("Enter number with prefix","34"),0))
//Flags:
//Name: [test] Infinimulti
var c = 10;
var num = [0,0];
function menu(){
var opt = prompt("Memory number:\n"+writeNum(num)+"\n\nChoose:\n1: Add\n2:Multiply",0);
switch(opt){
case 0: return;
case 1: num=addNum(num); break;
case 2: num=multiNum(num);break;
}
function inputNum(){
var prov = prompt("Write the number:",0);
prov=parseInt(outp);
var outp=[prov>=0,0];
prov=Math.abs(prov);
var i=1;
while(prov>0){
outp[i]=prov%c;
prov=(prov-prov%c)/c;
++i;
}
return outp;
}
function writeNum(it){
var outp=it[0]>=0?'+':'-';
for(var i=1;i<it.length;++i){
outp+=it[i];
return outp;
}
function addNum(it){
var num2=inputNum();
var carry=0;
for(var i=1;i<Math.max(it.length,num2.length;++i){
var sum=
}
}
//Flags: app
//Name: [to wiki] selectable items
//config
var velocity = 0.2;//The default velocity. The bigger, the faster (between (0,1] warning: outside that range it can crash)
var frecuency = 60;//ticks per second [Recommended 60] (set to 0 for fastest possible, in case you have a lot of items)
//name
var name="selectable";
//tags
var tag="selectable"
//classes
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface");
//vars
var e=LL.getEvent();
var i=e.getItem();
var c=e.getContainer();
var script=LL.getCurrentScript();
var t=c.getTag(tag);
if(c==null){
//no container, just exit
Android.makeNewToast("no container", true).show()
return
}
//more vars
var s=c.getItemByName(name);
var bools;//global variable used in the installation
if(e.getSource()=="MENU_APP"){
//script run manually
if(t==null){
install();
}else{
repair();
}
return
}
if(s==null){
//no selectable item
if(confirm("warning, no selectable item found. Do you want to begin the installation?"))install();
return
}
if(i==null){
//no item selected, deselecting
s.setVisibility(false);
c.setTag(tag,-1);
return;
}
if(i.getId()==t){
//launch item
i.launch();
s.setVisibility(false);
c.setTag(tag,-1);
}else{
//select item
c.setTag(tag,i.getId());
//always above everything
var max=c.getItems().getLength()-1;
if(c.getItemZIndex(s.getId())!=max)c.setItemZIndex(s.getId(),max);
if(s.isVisible()){
//move with animation
//token to stop if another instance is running
var sessiontoken;
do{
sessiontoken=""+Math.random();
}while(sessiontoken==script.getTag());
script.setTag(sessiontoken);
var debug=false;
var dat=[0,i.getPositionX(),i.getPositionY(),i.getScaleX(),i.getScaleY(),i.getWidth(),i.getHeight(),i.getRotation()];
var n=center(dat);
dat[1]+=n[0];
dat[2]+=n[1];
move(s,dat);
}else{
//move without animation
s.setSize(i.getWidth(),i.getHeight());
s.setScale(i.getScaleX(),i.getScaleY());
s.setRotation(i.getRotation());
s.setPosition(i.getPositionX(),i.getPositionY());
s.setVisibility(true);
}
}
//will ask to choose between install or uninstall
function repair(){
var builder = new AlertDialog.Builder(LL.getContext());
builder.setTitle("What do you want to do?");
builder.setCancelable(true);
builder.setPositiveButton("Uninstall",new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
setTimeout(uninstall,0);
}
});
builder.setNeutralButton("Repair",new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
setTimeout(install,0);
}
});
builder.setNegativeButton("Cancel",null);
builder.show();
}
//will install/uninstall
function uninstall(){install(true)};
function install(un){
if(!confirm("Welcome to the 'selectable item' "+(un?"uninstallation":"installation")+" process\nThis will prepare this "+c.getType()+" ("+c+")\n Do you want to continue?")) return;
var act=un?"Revert to unset":"Set to launch this script";
var installs=[act+" the default tap action",act+" the tap background action"];
bools=[true,true,false];
if(s==null&&!un){
installs.push("Create selectable item");
bools[2]=true;
}
if(s!=null&&un){
installs.push("Remove selectable item");
bools[2]=true;
}
var builder = new AlertDialog.Builder(LL.getContext());
var listener = new DialogInterface.OnMultiChoiceClickListener(){
onClick:function(dialog,which,isChecked){
bools[which]=isChecked;
}
};
builder.setMultiChoiceItems(installs,bools,listener);
builder.setTitle("Choose things to do");
builder.setCancelable(true);
builder.setPositiveButton((un?"Uninstall":"Install"),new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
installSelected(un);
}
});
builder.setNegativeButton("Exit",null);
builder.show();
}
//will do the things chosen in the installation
function installSelected(un){
if(!(bools[0]||bools[1]||bools[2])){
Android.makeNewToast("Nothing done", true).show();
return;
}
c.setTag(tag,(un?null:-1));
LL.save()
var prop=c.getProperties().edit();
if(bools[0]){
if(un)prop.setEventHandler("i.tap",EventHandler.UNSET,null)
else prop.setEventHandler("i.tap",EventHandler.RUN_SCRIPT,script.getId())
}
if(bools[1]){
if(un)prop.setEventHandler("bgTap",EventHandler.UNSET,null)
else prop.setEventHandler("bgTap",EventHandler.RUN_SCRIPT,script.getId())
}
prop.commit();
if(bools[2]){
if(un){
c.removeItem(c.getItemByName(name));//get the item again because commit reloads the container
}else{
s=c.addShortcut("Selectable item. It is recommended to set a nine patch as background and hide the label",new Intent(),e.getTouchX(),e.getTouchY());
//properties
s.setName(name);
s.getProperties().edit()
.setBoolean("i.onGrid",false)
.setBoolean("s.iconVisibility",false)
.setBoolean("i.enabled",false)
.setInteger("s.labelMaxLines",10)
.commit();
//default background image
var im=LL.createImage(100,100);
var p=new Paint();
p.setColor(0xffffffff);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(5);
im.draw().drawRect(0,0,100,100,p);
s.setBoxBackground(im,"n",true)
}
}
Android.makeNewToast((un?"Uninstallation":"Installation")+" completed.\nPlease restart your device...",true).show();
Android.makeNewToast("...just joking :P",true).show();
}
//custom lerp. It moves the item a bit and repeat, stops when finish, when LL is not active or when another instance of the script runs
function move(item,dat){
//another script is running
if( sessiontoken!=script.getTag()){return;}
//actual data
var now = [
0,
item.getPositionX(),
item.getPositionY(),
item.getScaleX(),
item.getScaleY(),
item.getWidth(),
item.getHeight(),
item.getRotation()
];
var n=center(now);
now[1]+=n[0];
now[2]+=n[1];
//calculate the next step
var cut=[0,0.5,0.5,0.01,0.01,1,1,0.99];
var step = [];
var flag = "";
for(var j=dat.length-1;j>0;--j){
step[j]=dat[j]-now[j];
if(Math.abs(step[j])>cut[j]){
flag+=j;
if (cut[j]==1){
step[j]=now[j]+(step[j]>0?Math.max(step[j]*velocity,cut[j]):Math.min(step[j]*velocity,-cut[j]));
}else step[j]=now[j]+step[j]*velocity;
}else step[j]=dat[j];
}
//if nothing changed or LL paused
if( flag=="" || LL.isPaused()){
item.setScale(dat[3],dat[4]);
item.setSize(dat[5],dat[6]);
item.setRotation(dat[7]);
var d = center(dat);
item.setPosition(dat[1]-d[0],dat[2]-d[1]);
if(debug)item.setLabel(item.getLabel());
return;
}
if(debug)item.setLabel(flag+"@"+item.getLabel());
//sets the next step and repeat
item.setSize(step[5],step[6]);
item.setScale(step[3],step[4]);
item.setRotation(step[7]);
var s=center(step);
item.setPosition(step[1]-s[0],step[2]-s[1]);
velocity=(1+999*velocity)/1000;
setTimeout(function(){ move(item,dat);},frecuency==0?0:1000/frecuency);
}
//custom function to get the center of the item d=[,,,sizx,sizy,scax,scay,rot]
function center(d){
var c=[];
var r=d[7]*Math.PI/180; c[0]=Math.abs(d[4]*d[6]*Math.sin(r))/2+Math.abs(d[3]*d[5]*Math.cos(r))/2;
c[1]=Math.abs(d[3]*d[5]*Math.sin(r))/2+Math.abs(d[4]*d[6]*Math.cos(r))/2;
return c;
}
//Flags: custom
//Name: [tool] Create notification
//bind classes
LL.bindClass("android.app.Notification");
LL.bindClass("android.app.NotificationManager");
LL.bindClass("android.content.Context");
LL.bindClass("android.app.PendingIntent");
LL.bindClass("android.R");
//vars used also in the returned functions
var cntx=LL.getContext();//if you need a 'context' for a java function, this is probably what you need.
var nm=cntx.getSystemService(Context.NOTIFICATION_SERVICE);//returns the service used to work with notifications
var text = prompt("Text","");
if(text==null) return;
var pos=text.indexOf("\n");
lines = pos==-1 ? [text,""] : [ text.substring(0,pos), text.substring(pos+1) ];
if(lines[0].length>40){
lines=["",lines[0]+"\n"+lines[1]];
}
//if there wasn't data, create the notification
var id=0;//single identifier for each pending intent, used in the helper function
//create the notification from a builder
var n=Notification.Builder(cntx,"script")//start the builder
.setContentTitle(lines[0])//title
.setContentText(lines[1])//main text
.setContentInfo("notification LL")//information
.setSmallIcon(R.drawable.ic_dialog_info)//small icon
//.setSmallIcon(R.color.transparent)
.setSubText("info")//secondary text
.setAutoCancel(true)//set to true to cancel when clicking
.setOngoing(false)
//you can add more things like sound, vibration, color...
//search 'notification.builder'
.build();//finish the builder and returns a ready notification
nm.notify(0,n);//show the notification. If you want to show more than one you need to set a different first number for each
//Flags: custom
//Name: [tool] Disable scripts
var ck=false;//if false, enabled scripts will be checked. If true, enabled scripts will be unchecked
//clases
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface");
//parameters
var list=LL.getAllScriptMatching(Script.FLAG_ALL);
var fd=Script.FLAG_DISABLED;
var states=[];
var names=[];
var own;
for(var t=0,tt=0;t<list.getLength();++t){
var s=list.getAt(t);
if(s.getId()==LL.getCurrentScript().getId()){
own=t;
continue;
}
states[tt]=s.hasFlag(fd)==ck;
names[tt]=s.getName();
++tt;
}
var builder=new AlertDialog.Builder(LL.getContext());
builder.setTitle((ck?"Disabled":"Enabled")+" scripts");
builder.setMultiChoiceItems(names,states,new DialogInterface.OnMultiChoiceClickListener(){onClick:function(dialog,which,checked){
list.getAt(which>=own?which+1:which).setFlag(fd,checked==ck);
}});
builder.setNeutralButton("Close",null);
builder.create().show();
//Flags: app item custom
//Name: [tool] Fast Run Tool
/*
Script: Fast Run Tool
Original by: TrianguloY
This script is provided as is. Public domain.
You are free to use, duplicate and modify it without restriction.
If you want to share it (modified or not) please don't change the first part of this header.
Modified by: <unmodified>
*/
/*config*/
var fastRunTool_runData = true;//enable this to run passed scripts as data when using a shortcut
var fastRunTool_reminder = true;//whether to show or not the previous input in the alert description
/*end of config*/
/*Available vars*/
var e = getEvent();//event
var c = e.getContainer();//container
var i = e.getItem();//item
var cntx = e.getScreen().getContext();//context
/*end of available vars*/
/*available functions*/
//helper function to show a toast in a shorter way
function toast(say){
if(say==null)say="null";
self.toast(say);
}
//deprecated. helper function to bind a class in a shorter way
function bind(class){
return bindClass(class);
}
//deprecated. sets and returns the item default tag
function iTag(setnew){
if(setnew!=undefined){
if(setnew=='null')setnew=null; i.setTag(setnew);
}
return i.getTag();
}
//deprecated. sets and returns the container default tag
function cTag(setnew){
if(setnew!=undefined){
if(setnew=='null')setnew=null; c.setTag(setnew);
}
return c.getTag();
}
//evaluates the func function for each item in container (c if null)
function foreach(func,container){
if(container==null)container=c;
var items=container.getItems();
for(var t=0;t<items.getLength();++t)func(items.getAt(t));
}
//this returns a string with the properties/methods of the object.
//optionally will only return those with 'search' in it
function objects(obj,search){
if(obj==""||obj==null) return "";//no valid object
var keys;
try{
keys=Object.getOwnPropertyNames(obj);//magic line ;)
}catch(e){
keys=Object.keys(obj);//in case the magic line fails
}
keys.sort(sortable);
var text="";//the output
for(t in keys){
var key=keys[t];
var prop;
try{
prop=""+obj[key];//when calling that key
}catch(e){
prop=""+e;//there were an error calling the key
}
if(
search!=null
&&
key.toLowerCase().indexOf(search.toLowerCase())==-1
&&
prop.toLowerCase().indexOf(search.toLowerCase())==-1
)continue;//searching not found
text+=key+" : "+prop+"\n";
if(prop[prop.length-1]!="\n")text+="\n";
}
return text;
}
/*end of available functions*/
//run from data
var fastRunTool_datatorun=LL.getEvent().getData();
if(!fastRunTool_runData && fastRunTool_datatorun!=null){
toast("Running scripts from shortcuts is disabled. Change it in the script settings if you want to");
return;
}
if(fastRunTool_datatorun!=null&&fastRunTool_datatorun!=""){
try{
eval("function fastRunTool(){\n"+fastRunTool_datatorun+"\n}");
fastRunTool();
}catch(e){
prompt("Error running script from data:\n"+fastRunTool_datatorun,e);
}
return;
}
//if no data to run, use the inputted one
if(fastRunTool_datatorun==""){
try{
eval("function fastRunTool(){\n"+LL.getScriptTag()+"\n}");
fastRunTool();
}catch(e){
prompt("Error running script from tag:\n"+fastRunTool_datatorun,e);
}
return;
}
//normal run
var fastRunTool_repeat=true;//will allow to run again after an error
while(fastRunTool_repeat){fastRunTool_repeat=false;
var fastRunTool_text = LL.getScriptTag() || "";
var fastRunTool_description =
"Vars: e-event, cntx-context"+
(c!=null? ", c-container":", [no container]")+
(i!=null? ", i-item":", [no item]")+
"\n"+
"Functions: "+
//toast(String)"+
//", boolean bind(String)"+
//(c!=null ? ", String cTag(String)":"")+
//(i!=null ? ", String iTag(String)":"")+
"void foreach(function(item),{container (c)})"+
", String objects(Object,{search})"+
(fastRunTool_reminder ? "\n\nPrevious input:\n"+
fastRunTool_text+
"\n_____________________________________" : "");
//Change this description if you want
//this asks for the code to run
var fastRunTool_out = prompt(fastRunTool_description,fastRunTool_text);
if(fastRunTool_out==null) return;//cancel
LL.setScriptTag(fastRunTool_out);//save
var fastRunTool_torun=fastRunTool_out;
//gets the last line.
var fastRunTool_last=fastRunTool_out.lastIndexOf("\n")+1;//
var fastRunTool_line=fastRunTool_out.substr(fastRunTool_last);
//If no ';' , '}' or '//' found encapsulate it inside a prompt
if(fastRunTool_line.search(/(\;|\}|\/\/)/)==-1) fastRunTool_torun=fastRunTool_out.substr(0,fastRunTool_last)+"fastRunTool_repeat=true;prompt('»"+fastRunTool_line.replace(/'/g,"\\'")+"«',fastRunTool_toStringFormatted("+fastRunTool_line+"));";
//evaluates the code
fastRunTool_torun="function fastRunTool(){"+fastRunTool_torun+"\n}";
try{
eval(fastRunTool_torun);
fastRunTool();
}catch(fastRunTool_error){
//error found. Showing and repeating
fastRunTool_repeat=prompt(
fastRunTool_out.split("\n").map(function(v,i,a){return ":"+(i+1)+":"+v;}).join("\n"),
fastRunTool_error.name+" at line "+fastRunTool_error.lineNumber+"\n"+fastRunTool_error.message)!=null;
}
}//end of repeat
//custom functions
//returns the input as string or as a formatted string if already
function fastRunTool_toStringFormatted(a){
return typeof a!="string" ? ""+a : '"'+a.replace(/"/g,'\\"')+'"' ;
}
//sorts the elements keeping the 'get' toghether
function sortable(a,b){
var isgeta=false;
var isgetb=false;
if(a.substring(0,3)=="get"){
a=a.substring(3,a.length);
isgeta=true;
}else if(a.substring(0,2)=="is"){
a=a.substring(2,a.length);
isgeta=true;
}
if(b.substring(0,3)=="get"){
b=b.substring(3,b.length);
isgetb=true;
}else if(b.substring(0,2)=="is"){
b=b.substring(2,b.length);
isgetb=true;
}
a=a.toLowerCase();
b=b.toLowerCase();
return a<b?-1:a>b?1: ( isgeta&&!isgetb?-1 : !isgeta&&isgetb?1: 0 );
}
//Flags: item
//Name: [tool] Intent editor
var it=LL.getEvent().getItem();
if(it==null){alert("Run this script from an item");return;}
var I=it.getIntent();
I=Intent.parseUri(prompt2("URI",I.toUri(0)),0);
if(confirm("show individual parts?")){
I=I.setAction(prompt2("Action",I.getAction()));
I=I.setPackage(prompt2("Package",I.getPackage()));
//I.setType(prompt2("Type",I.getType()));
var out=prompt2("Component",I.getComponent()==null?null:I.getComponent().flattenToString());
if(out!=null)I.setComponent(ComponentName.unflattenFromString(out));
var extras=I.getExtras();
if(extras==null){
alert("no extras");
}else{
alert("extras:\n"+extras);//debug alert
var keys =I.getExtras().keySet();
var iterator = keys.iterator(); while(iterator.hasNext()){
//this will run once for each extra
var extraname=iterator.next();
var extradata=extras.get(extraname);
/*
TODO: be able to edit it
warning, ints will need to be converted to ints, because JavaScript only have floats
*/
alert(extraname+" ("+(typeof extradata)+"):\n"+extradata);
}
}
//need a statement to add elements
}
if(it.getIntent().toUri(0)!=I.toUri(0) && confirm("Do you want to save the new intent?"))it.setIntent(I);
function prompt2(title,input){
//custom prompt function to check for nulls automatically
var out=prompt(title,input==null?"":input);
if(out==null)out=input;
else if(out=="")out=null
return out;
}
//Flags: custom
//Name: [tool] launcher cleanup
LL.bindClass("java.io.File");
var deletefiles=confirm("Do you want to delete the files? (cancel to show the log only)")&&confirm("MAKE SURE YOU HAVE A BACKUP!!! Do you really want to continue?");
var cids=[];//container ids
var iids=[];//item ids
var d=LL.getAllDesktops();
for(var i=0;i<d.getLength();++i)compute(LL.getContainerById(d.getAt(i)));
compute(LL.getContainerById(99));
compute(LL.getContainerById(32767));
function compute(c){
if(cids.indexOf(c.getId()+"")!=-1) return;
cids.push(c.getId()+"");
var its=c.getItems();
for(var i=0;i<its.getLength();++i){
var it=its.getAt(i);
iids.push(it.getId()+"");
if(it.getType()=="Folder"||it.getType()=="Panel")compute(it.getContainer());
}
}
//alert(cids+"\n\n"+iids);
var log="";
var dir="data/data/net.pierrox.lightning_launcher_extreme/files/pages"
var main=new File(dir);
var pages=main.listFiles();
for(var t=0;t<pages.length;++t){
var pag=pages[t];
if(cids.indexOf(pag.getName()+"")==-1){
log+="\nunused container: "+pag.getName();
if(deletefiles)DeleteRecursive(pag);
}else{
//check items
var icons=(new File(dir+"/"+pag.getName()+"/icon")).listFiles();
if(icons==null) continue;
for(var tt=0;tt<icons.length;++tt){
var icon=icons[tt];
var iconid=parseInt(icon.getName())+""
if(iids.indexOf(iconid)==-1&&iconid!="NaN"){
log+="\nunused icon: "+icon.getName()+" in container "+pag.getName();
if(deletefiles)icon.delete();
}
}
}
}
log=(deletefiles?"Deleting activated. The following files have been deleted:":"Check mode only, no files were deleted:")+(log==""?"\n>no unused files found<":log);
LL.writeToLogFile("\n\n\n"+log,true);
alert(log);
function DeleteRecursive( fileOrDirectory) {
if (fileOrDirectory.isDirectory()){
var files= fileOrDirectory.listFiles()
for (var i=0;i<files.length;i++)
DeleteRecursive(files[i]);
}
fileOrDirectory.delete();
}
//Flags: custom
//Name: [tool] launcher files
LL.bindClass("java.io.BufferedReader");
LL.bindClass("java.io.FileReader");
LL.bindClass("java.io.File");
LL.bindClass("java.io.FileWriter");
if(typeof resultCode!="undefined"){
if(data==null) return;
if(confirm("edit as image? otherwise as text")){
var intent =new Intent();
intent.setComponent(ComponentName.unflattenFromString("net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.ImageCropper"));
intent.putExtra("i",data.getExtra("f"));
LL.startActivity(intent);
}else{
edit(data.getExtra("f"));
}
return;
}
var intent =new Intent();
intent.setComponent(ComponentName.unflattenFromString("net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.FilePicker"));
//intent['putExtra(java.lang.String,java.lang.String[])']("e",[]);
intent.putExtra("p","data/data/net.pierrox.lightning_launcher_extreme");
Android.makeNewToast("Choose a file to edit",true).show();
LL.startActivity(intent);
return
LL.startActivityForResult(intent,LL.getCurrentScript(),null);
function edit(path){
var inp=read(path);
var oup=prompt(path,inp);
if(oup!=null&&oup!=inp){
if(oup==""&&confirm("you deleted the content, do you want to delete the whole file? (otherwise it will ask to save a blank string)")&&confirm("WARNING, delete some files can corrupt the launcher, make sure you have a backup and you know what you are doing!!!!")){
deletefile(path);
return;
}
if(confirm("file was modified, do you want to save it?")&&confirm("WARNING, wrong data can corrupt the launcher, make sure you have a backup and you know what you are doing!!!!"))write(path,oup);
}
}
function read(filePath){
var file=new File(filePath);
var r=new BufferedReader(new FileReader(file));
var s="";
var l;
while((l=r.readLine())!=null)s+=(l+"\n");
r.close();
return s.substring(0, s.length - 1);
}
function write(path,s){
var stream = new FileWriter(new File(path));
try {
stream.write(s);
} finally {
stream.close();
}
}
function deletefile(path){
(new File(path)).delete();
}
//Flags: app custom
//Name: [tool] logcat reader
LL.bindClass("java.lang.Runtime");
LL.bindClass("java.io.BufferedReader");
LL.bindClass("java.io.InputStreamReader");
if(confirm("Do you want to read the log?")) readlog();
if(confirm("Do you want to delete the log?"))deletelog();
function readlog(){
var mLogcatProc = Runtime.getRuntime().exec(["logcat","-d","-v","long"]);
var reader = new BufferedReader(new InputStreamReader
(mLogcatProc.getInputStream()));
var line;
var log = "";
while ((line = reader.readLine()) != null)
{
log+=line+"\n\n";
}
prompt("log",log);
}
function deletelog(){
Runtime.getRuntime().exec(["logcat","-c"])
}
//Flags: app item custom
//Name: [tool] Lukas's multi tool
//Created by Lukas Morawietz in collaboration with TrianguloY
//import java classes
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.app.ProgressDialog");
LL.bindClass("android.content.DialogInterface");
LL.bindClass("android.os.Environment");
LL.bindClass("android.R");
LL.bindClass("android.widget.ExpandableListView");
LL.bindClass("android.widget.ImageView");
LL.bindClass("android.widget.LinearLayout");
LL.bindClass("android.widget.ListView");
LL.bindClass("android.widget.NumberPicker");
LL.bindClass("android.widget.SimpleAdapter");
LL.bindClass("android.widget.SimpleExpandableListAdapter");
LL.bindClass("android.widget.ScrollView");
LL.bindClass("android.widget.TextView");
LL.bindClass("java.io.File");
LL.bindClass("java.io.BufferedReader");
LL.bindClass("java.io.FileReader");
LL.bindClass("java.io.FileWriter");
LL.bindClass("java.util.HashMap");
LL.bindClass("java.util.ArrayList");
var hasItem=(LL.getEvent().getItem()!=null);
//define Strings to display
var title="What do you want to do?";
var items=[]
var info=["Information",[]];
info[1].push("Event");
info[1].push("Container");
if(hasItem){
info[1].push("Item");
info[1].push("Intent");
info[1].push("Icon");
}
var itemUtils=["Item Utilities",[]];
itemUtils[1].push("Attach/Detach all Items");
itemUtils[1].push("Resize all detached Items");
itemUtils[1].push("Delete all Items");
itemUtils[1].push("Move Pages");
var other = ["Other",[]];
other[1].push("Reset Tag");
other[1].push("Reset Tool");
other[1].push("Save changes");
other[1].push("Delete recent app history");
items.push(info);
items.push(itemUtils);
items.push(other);
//normal run
if(typeof resultCode==='undefined') expandableList(items,mainOnClick,title);
//user has selected a file to import
else import_handleInput();
//handle user selection
function mainOnClick(groupPosition,childPosition){
switch(groupPosition){
case 0://Information
switch(childPosition){
case 0://Event related
eventData();
break;
case 1://container related
containerData()
break;
case 2://item related
itemData();
break;
case 3://intent
intentData();
break;
case 4://icon
iconData();
break;
}
break;
case 1://item utilities
switch(childPosition){
case 0://Attach/Detach all items
attachDetachAll();
break;
case 1://resize detached items
resizeAllDetached();
break;
case 2://delete items
deleteAll();
break;
case 3://move pages
movePages();
break;
}
break;
case 2://other
switch(childPosition){
case 0://reset Tag
resetTags();
break;
case 1://reset tool by trianguloY, ask him how it works :D
resetTool();
break;
case 2:
saveLayout();
break;
case 3:
resetRecents();
break;
}
break;
}
}
function eventData(){
var e=LL.getEvent();
try{ //test if event contains touch data
e.getTouchScreenX();
var ok=true;
}
catch(Exception){
var ok=false;
}
text("Source: "+e.getSource()+"\nDate: "+e.getDate()+"\nContainer: "+e.getContainer()+"\nItem: "+e.getItem()+(ok?("\nTouch: "+e.getTouchX()+","+e.getTouchY()+"\nTouch (Screen): "+e.getTouchScreenX()+","+e.getTouchScreenY()):""),"Event Information");
}
function containerData(){
var c=LL.getEvent().getContainer();
var t=c.getType();//Differentiate between Desktop and other containers
//read Tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+c.getId()+"/conf");
var data=JSON.parse(s);
var tags="Default: "+c.getTag();
for(property in data.tags)
tags+="\n"+property+": "+data.tags[property];
text("Type: "+t+"\nName/Label: "+(t=="Desktop"?c.getName():c.getOpener().getLabel())+"\nID: "+c.getId()+"\nSize: "+c.getWidth()+","+c.getHeight()+"\nBoundingbox: "+c.getBoundingBox()+"\nCell Size: "+c.getCellWidth()+","+c.getCellHeight()+"\nCurrent Position: "+c.getPositionX()+","+c.getPositionY()+"\nCurrent Scale: "+c.getPositionScale()+"\nTags: "+tags+"\nItems: "+c.getItems(),"Container Information");
}
function itemData(){
var i=LL.getEvent().getItem();if(i==null)//check if event contains item
text("no item found","Error 5");
//read tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+LL.getEvent().getContainer().getId()+"/items");
var all=JSON.parse(s).i;
var x;
var item;
for(x=0;x<all.length;x++){
item=all[x];
if(item.b==i.getId())break;
}
if(x==all.length){
text("Can't find Tags","Error 6");
return;
}
var tags="Default: "+i.getTag();
for(property in item.an){
if(property=="_")continue;
tags+="\n"+property+": "+item.an[property];
}
text("Label: "+i.getLabel()+"\nType: "+i.getType()+"\nID: "+i.getId()+"\nSize: "+i.getWidth()+","+i.getHeight()+"\nPosition: "+i.getPositionX()+","+i.getPositionY()+"\nScale: "+i.getScaleX()+","+i.getScaleY()+"\nAngle: "+i.getRotation()+"\nCenter: "+center(i)+((i.getType()=="Shortcut"||i.getType()=="Folder")?"\nIntent:"+i.getIntent():"")+"\nTags: "+tags,"Item Information");
}
function intentData(){
it=LL.getEvent().getItem();
if(it==null || item.getType()!="Shortcut")text("No Intent found.","Error 1");
else text("Intent: "+it.getIntent()+"\nExtras: "+it.getIntent().getExtras(),"Intent Information");
}
function iconData(){
it=LL.getEvent().getItem();
//create view structure
var root=new LinearLayout(LL.getContext());
root.setOrientation(LinearLayout.VERTICAL);
//check for all kinds of images in this item and add them to the view if there are any
addImageIfNotNull(root,it.getBoxBackground("n"),"Normal Box Background");
addImageIfNotNull(root,it.getBoxBackground("s"),"Selected Box Background");
addImageIfNotNull(root,it.getBoxBackground("f"),"Focused Box Background");
if(it.getType()=="Shortcut"){
addImageIfNotNull(root,image=it.getDefaultIcon(),"Default Icon");
addImageIfNotNull(root,image=it.getCustomIcon(),"Custom Icon");
}
if(root.getChildCount()>0){ //at least one image found
var scroll=new ScrollView(LL.getContext());
scroll.addView(root);
customDialog(scroll,"Icon");
}
else Android.makeNewToast("No Image Data available",true).show(); //no image found
}
function attachDetachAll(){
var items=LL.getEvent().getContainer().getItems();
var attachDetach = function(toGrid){
for(x=0;x<items.length;x++)
{
var i=items.getAt(x);
i.getProperties().edit().setBoolean("i.onGrid",toGrid).commit();
}
Android.makeNewToast("Done!",true).show();
}
var attach = function(){attachDetach(true);}
var detach = function(){attachDetach(false);}
chooser([function(){},attach,detach],["Cancel","Attach","Detach"],"Do you want to attach or detach all items?","MultiTool");
}
function resizeAllDetached(){
var linearLayout = new LinearLayout(LL.getContext());
var c = LL.getEvent().getContainer();
linearLayout.setOrientation(LinearLayout.VERTICAL);
var widthText = new TextView(LL.getContext());
widthText.setText("Width: ");
linearLayout.addView(widthText);
var widthPicker = new NumberPicker(LL.getContext());
widthPicker.setMinValue(1);
widthPicker.setMaxValue(9999);
widthPicker.setValue(c.getCellWidth());
linearLayout.addView(widthPicker);
var heightText = new TextView(LL.getContext());
heightText.setText("Height: ");
linearLayout.addView(heightText);
var heightPicker = new NumberPicker(LL.getContext());
heightPicker.setMinValue(1);
heightPicker.setMaxValue(9999);
heightPicker.setValue(c.getCellHeight());
linearLayout.addView(heightPicker);
var onClick = function(){
var s=[widthPicker.getValue(),heightPicker.getValue()];
var items=c.getItems();
for(var a=0;a<items.length;a++)
items.getAt(a).setSize(s[0],s[1]);
}
customConfirmDialog(linearLayout,"To which size?",onClick);
}
function deleteAll(){
var f = function(){
var c=LL.getEvent().getContainer();
var i=c.getItems();
for(a=0;a<i.length;a++)
c.removeItem(i.getAt(a));
}
chooser([function(){},f],["No","Yes"],"Are you sure?","Delete all items");
}
function movePages(){
var cont=LL.getEvent().getContainer();
var items=cont.getItems();
var cWidth=cont.getWidth();
var cHeight=cont.getHeight();
var cellsFloatX=cWidth/cont.getCellWidth();
var cellsFloatY=cHeight/cont.getCellHeight();
var cellsX=Math.round(cellsFloatX);
var cellsY=Math.round(cellsFloatY);
var f=function(){
try{
//page(s) selection
var s=prompt("Which page do you want to move? (* for all) input has to be x,y (e.g. *,* for all pages)","").split(",");
var move=JSON.parse("[\""+s[0]+"\",\""+s[1]+"\"]");
var done=true;
}
catch(Exception){
var done=false;
}
//check for valid input
if(!done||move==null||move[0]==null||(move[0]!="*"&&isNaN(parseInt(move[0])))||move[1]==null||(move[1]!="*"&&isNaN(parseInt(move[1])))){
Android.makeNewToast("Invalid input",true).show();
return;
}
//format to int if needed
if(move[0]!="*")move[0]=parseInt(move[0]);
if(move[1]!="*")move[1]=parseInt(move[1]);
try{
//user selection: destination
var dist=JSON.parse("["+prompt("How far do you want to move? input has to be x,y (e.g. 1,0 for one page right)","")+"]");
var done=true;
}
catch(Exception){
var done=false;
}
//check for valid input
if(!done||dist==null||dist[0]==null||isNaN(dist[0])||dist[1]==null||isNaN(dist[1])){
Android.makeNewToast("Invalid input",true).show();
return;
}
if(dist[0]==0&&dist[1]==0)return;//if nothing to do, do nothing :P
//do the movement
for(var i=items.getLength()-1;i>=0;--i){
var item=items.getAt(i);
var pos=[item.getPositionX(),item.getPositionY()];
//check if item should be moved
if((move[0]=="*" || (pos[0]>=cWidth*move[0] && pos[0]<cWidth*(move[0]+1))) && (move[1]=="*" || (pos[1]>=cHeight*move[1] && pos[1]<cHeight*(move[1]+1)))){
var prop=item.getProperties();
//handle pinned item
var xx=1,yy=1;
var pinMode=prop.getString("i.pinMode");
if(pinMode[0]=="X")xx=0;
if(pinMode.indexOf("Y")!=-1)yy=0;
//move it
if(prop.getBoolean("i.onGrid")){
var cell=item.getCell();
item.setCell(cell.getLeft()+cellsX*dist[0]*xx,cell.getTop()+cellsY*dist[1]*yy,cell.getRight()+cellsX*dist[0]*xx,cell.getBottom()+cellsY*dist[1]*yy);
}
else
item.setPosition(pos[0]+cWidth*dist[0]*xx,pos[1]+cHeight*dist[1]*yy);
}
}
LL.save();
}
//check for safe cell sizes
if(Math.abs(cellsFloatX-cellsX)>0.00001||Math.abs(cellsFloatY-cellsY)>0.00001)
chooser([function(){},f]["No","Yes"],"The cells don't fill the screen as an exact vertical and/or horizontal number.\nDo you want to continue?","Warning");
else f();
}
function resetTags(){
var d=LL.getEvent().getContainer();
var i=LL.getEvent().getItem();
if(i!=null){ //Items Tag
//read tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+LL.getEvent().getContainer().getId()+"/items");
var all=JSON.parse(s).i;
var x;
var item;
for(x=0;x<all.length;x++){
item=all[x];
if(item.b==i.getId())break;
}
if(x==all.length){
text("Can't find Tags","Error 6");
return;
}
var tags=[];
for(property in item.an)
tags.push(property);
//If there are no Tags, do nothing
if(tags.length==0){
text("No Tags found","Error 7");
return;
}
//Option to delete all tags added to list
tags.unshift("All Tags");
var onClick = function(dialog,id){
//delete all selected Tags
alert(id+": "+tags[id]);
if(id==0)tags.shift();
else tags=[tags[id]];
for(var y=0;y<tags.length;y++)
i.setTag(tags[y].toString(),null);
Android.makeNewToast("Deleting tag(s) done!",true).show();
LL.save();
}
//ask user for selection
list(tags,onClick,"Which Tag do you want to reset?");
}
else{ //Container Tags
//read Tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+d.getId()+"/conf");
var data=JSON.parse(s);
var tags=[];
for(property in data.tags)
tags.push(property);
//Add the default tag to the List
if(data.tag!=null)tags.push("_");
//If there are no Tags, do nothing
if(tags.length==0){
text("No Tags found","Error 7");
return;
}
//Option to delete all tags added to list
tags.unshift("All Tags");
var onClick = function(dialog,id){
//delete all selected Tags
if(id==0)tags.shift();
else tags=[tags[id]];
for(var x=0;x<tags.length;x++){
if(tags[x]=="_")d.setTag(null);
else d.setTag(tags[x].toString(),null);
}
Android.makeNewToast("Deleting tag(s) done!",true).show();
LL.save();
}
//ask user for selection
list(tags,onClick,"Which Tag do you want to reset?");
}
}
function resetTool(){
var cont=LL.getEvent().getContainer();
var items=cont.getItems();
var listItems = ["Cell (only grid items) [0,0]","Position (only free items) [0,0]","Rotation (only free items) [0]","Scale (only free items) [1,1]","Skew (only free items) [0,0]","Size (only free items) [cell size]","Visibility [true]"];
var listener = new DialogInterface.OnMultiChoiceClickListener(){
onClick:function(dialog,which,isChecked){
bools[which]=isChecked;
}
};
var bools=[false,false,false,false,false,false,false];
var builder = new AlertDialog.Builder(LL.getContext());
builder.setMultiChoiceItems(listItems,bools,listener);
builder.setTitle("Reset");
builder.setCancelable(true);
builder.setPositiveButton("Confirm",new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
for(var i=0;i<items.getLength();++i){
var t=items.getAt(i);
if(bools[0])t.setCell(0,0,1,1);
if(bools[1])t.setPosition(0,0);
if(bools[2])t.setRotation(0);
if(bools[3])t.setScale(1,1);
if(bools[4])t.setSkew(0,0);
if(bools[5])t.setSize(cont.getCellWidth(),cont.getCellHeight());
if(bools[6])t.setVisibility(true);
}
}
});
builder.show();
}
function saveLayout(){
LL.save();
Android.makeNewToast("Saved Layout",true).show();
}
function resetRecents(){
new File(LL.getContext().getFilesDir().getPath()+"/statistics").delete();
Android.makeNewToast("Recents resetted",true).show();
}
//function to display a grouped list where the user can select one item
//items should be an array containing arrays which first item is the group and the second item is an array of the items in this group
//onClickFunction has to have two arguments. first is group position, second is child position
function expandableList(items,onClickFunction,title){
var builder=new AlertDialog.Builder(LL.getContext());
var view=new ExpandableListView(LL.getContext());
//transform array of items into the correct format
var groupData=new ArrayList();
var childData=new ArrayList();
for(var x=0;x<items.length;x++)
{
var gd=new HashMap();
gd.put("root",items[x][0]);
var cd=new ArrayList();
groupData.add(gd);
for(var y=0;y<items[x][1].length;y++)
{
var cdMap=new HashMap();
cdMap.put("child",items[x][1][y]);
cd.add(cdMap);
}
childData.add(cd);
}
var mContext = LL.getContext().createPackageContext("com.faendir.lightning_launcher.multitool",0);
var layoutId = mContext.getResources().getIdentifier("list_item","layout","com.faendir.lightning_launcher.multitool");
//assign the items to an adapter
var adapter=new SimpleExpandableListAdapter(mContext,groupData,layoutId,["root"],[R.id.text1],childData,layoutId,["child"],[R.id.text1]);
//set function to run on Click to listener
var listener=new ExpandableListView.OnChildClickListener()
{
onChildClick:function(parent,view,groupPosition,childPosition,id)
{
dialog.dismiss();
setTimeout(function(){onClickFunction(groupPosition,childPosition);},0);
return true;
}
}
//assign adapter and listener to listview
view.setAdapter(adapter);
view.setOnChildClickListener(listener);
//finish building
builder.setView(view);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.cancel();}});
dialog=builder.create();
dialog.show();
}
//function to display a List in a Popup, where the user can select one item
function list(items,onClickFunction,title){
var builder=new AlertDialog.Builder(LL.getContext());
var listener=new DialogInterface.OnClickListener()
{
onClick:function(dialog,which)
{
dialog.dismiss();
setTimeout(function(){onClickFunction(dialog,which);},0);
return true;
}
}
builder.setItems(items,listener);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.cancel();}});//it has a Cancel Button
builder.show();
}
//function to display an alert like Dialog, but scrollable and with custom Title
function text(txt,title){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setMessage(txt);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNeutralButton("Close",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();}});
builder.show();
}
function chooser(functions,texts,txt,title){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setMessage(txt);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNeutralButton(texts[0],new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.dismiss();
setTimeout(functions[0],0);
}
});
if(functions.length>1)builder.setNegativeButton(texts[1],new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.dismiss();
setTimeout(functions[1],0);
}
});
if(functions.length>2)builder.setPositiveButton(texts[2],new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.dismiss();
setTimeout(functions[2],0);
}
});
builder.show();
}
function customDialog(view,title){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setView(view);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNeutralButton("Close",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();}});
builder.show();
}
function customConfirmDialog(view,title,onPositiveFunction){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setView(view);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();}});
builder.setPositiveButton("Confirm",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();setTimeout(onPositiveFunction,0);}});
builder.show();
}
//helper function for item related, compute the center of an item
function center(item){
var r=item.getRotation()*Math.PI/180;
var sin=Math.abs(Math.sin(r));
var cos=Math.abs(Math.cos(r));
var w=item.getWidth()*item.getScaleX();
var h=item.getHeight()*item.getScaleY();
return[item.getPositionX()+(w*cos+h*sin)*0.5,item.getPositionY()+(h*cos+w*sin)*0.5];
}
//helper function for sorting labels
function noCaseSort(a,b){
if(a.toLowerCase()>b.toLowerCase())return 1;
if(a.toLowerCase()<b.toLowerCase())return -1;
return 0;
}
function read(filePath){
var file=new File(filePath);
var r=new BufferedReader(new FileReader(file));
var s="";
var l;
while((l=r.readLine())!=null)s+=(l+"\n");
return s;
}
function addImageIfNotNull(root,image,txt){
if(image!=null)
{
var textView=new TextView(LL.getContext());
textView.setText(txt+" ("+image.getWidth()+"x"+image.getHeight()+")");
root.addView(textView);
var imageView=new ImageView(LL.getContext());
imageView.setImageBitmap(image.getBitmap());
root.addView(imageView);
}
}
//Flags: app item custom
//Name: [tool] objectKeys
var obj=prompt("element","");
if(obj==""||obj==null) return;
eval("obj="+obj);
var keys=Object.keys(obj);
keys.sort();
var text="";
for(t in keys){
g=keys[t];
text+=g+" : "+obj[g]+"\n";
}
prompt("",text);
//Flags: custom
//Name: [tool] scripts backup
//binds
LL.bindClass("java.io.File");
LL.bindClass("java.io.FileWriter");
LL.bindClass("android.os.Environment");
//-------------------------------------------------
var totalfiles=(new File(Environment.getExternalStorageDirectory()+"/LightningLauncher")).listFiles();
var backups=0;
for(var t=totalfiles.length-1;t>=0;--t)if(totalfiles[t].isFile())backups++;
if(backups==0/*&&confirm("Backup!!!!!")*/){
//open backup intent
LL.startActivity(Intent.parseUri("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.BackupRestore;end",0));
}
//-------------------------------------------------
var directory="LightningLauncher/Backup scripts";//use the slash as folder separator
var confirmation=false;//set to false to save without user interaction
var extradata=true;//if true it will save the flags and the name of the script in the file. set to false for an exact copy of the script
if(confirmation&&!confirm("Do you want to make a backup of the scripts?\n Old saved scripts will be overwritten, and deleted if they are not in the editor. Your current scripts won't be modified"))return;
directory=File.separator+directory.replace(/\//g,File.separator);//not necessary I guess, but just in case
// Create a new directory
var createDirectory = new File(Environment.getExternalStorageDirectory()+directory);
createDirectory.mkdirs();
//backup previous one, in case something goes wrong
var files=createDirectory.listFiles();
for(var i=files.length-1;i>=0;--i){
var file=files[i];
files[i]=new File(file.getAbsolutePath()+".tmp");
file.renameTo(files[i]);
}
//get all scripts
var scripts=LL.getAllScriptMatching(Script.FLAG_ALL);
//save current scripts
for(var t=scripts.getLength()-1;t>=0;--t){
var script=scripts.getAt(t);
// create a new file
var createFile = new File(Environment.getExternalStorageDirectory()+directory+File.separator+converttofile(script.getName())+" _ "+script.getId()+"_0x"+script.getId().toString(16)+".js");
createFile.createNewFile();
// create the content of the script
var content="";
if(extradata)content+="//Flags: "+
(script.hasFlag(Script.FLAG_APP_MENU)?"app ":"")+
(script.hasFlag(Script.FLAG_ITEM_MENU)?"item ":"")+
(script.hasFlag(Script.FLAG_CUSTOM_MENU)?"custom ":"")+
"\n"+
"//Name: "+script.getName()+
"\n";
content+=script.getText();
//write to file
var createFileWriter = new FileWriter(createFile, false);
createFileWriter.write(content);
createFileWriter.flush();
createFileWriter.close();
}
// readme file
var createFile = new File(Environment.getExternalStorageDirectory()+directory+File.separator+"[readme].txt");
createFile.createNewFile();
// write to the file
var createFileWriter = new FileWriter(createFile, false);
createFileWriter.write("This folder contains a backup of the scripts in the editor. Any file here will be deleted at the backup");
createFileWriter.flush();
createFileWriter.close();
//delete tmp files...perhaps I need to check before if nothing went wrong
for(var i=files.length-1;i>=0;--i){
files[i].delete();
}
Android.makeNewToast("Saved "+scripts.getLength()+" scripts", true).show();
function converttofile(n){
return n.replace(/[,./\:*?""<>|]/g,"_");
}
//Flags: app item custom
//Name: [tool] Url launcher
//check data, if found open that url
var data = getEvent().getData();
if(data != null){
open(data);
return;
}
//no data, check item. if found replace intent
var i = getEvent().getItem();
if(i != null && confirm("Do you want to set the intent of the item '"+i+"' to open a url? Warning! this will replace the existing intent!!!")){
setIntent(i);
return;
}
//no data nor item, check container. if found ask to create item
var c = getEvent().getContainer();
if(c != null && confirm("Do you want to create a new item to open a url when clicked?")){
createItem(c);
return;
}
//no data nor item nor container, just ask and open
if(confirm("Do you want to manually open a url? (for script testing purposes)")){
manual();
return;
}
//nothing
toast("No option selected :(")
//Opens the url in a browser
//Shows toast on error
function open(url){
if( !getBackgroundScreen().startActivity(createIntent(url)) ){
toast("The url '"+url+"' could not be opened.");
}
}
//returns an intent to open the url
function createIntent(url){
var intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
return intent;
}
//asks the user to enter a url
//returns the user input (null if cancelled)
function askUrl(){
return prompt("Write the url you want to open","https://");
}
//asks for a url
//opens it (nothing if cancelled)
function manual(){
var url = askUrl();
if(url == null) return;
open(url);
}
//asks the user a url
//sets the intent of item i to open that url (nothing if cancelled)
function setIntent(i){
var url = askUrl();
if(url == null) return;
i.setIntent(createIntent(url));
toast("item modified");
}
//asks the user a url and a name
//creates a new item in the container c to open that url (nothing if cancelled)
function createItem(c){
var url = askUrl();
if(url == undefined) return;
var name = prompt("Name of item?","Open "+url);
if(name == undefined) return;
var px = getEvent().getTouchX();
var py = getEvent().getTouchY();
var i = c.addShortcut(name,createIntent(url),px,py);
i.setDefaultIcon(Image.createTextIcon("Z",100,Color.GRAY,Color.TRANSPARENT,null));//"Z" is the web icon
toast("item added");
}
//Shows a toast with the message m
function toast(m){
Toast.makeText(getBackgroundScreen().getContext(),m,Toast.LENGTH_LONG).show()
}
//Flags: custom
//Name: [tool] variable editor
//classes
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface");
LL.bindClass("java.io.BufferedReader");
LL.bindClass("java.io.FileReader");
LL.bindClass("java.io.File");
LL.bindClass("android.view.ContextThemeWrapper");
LL.bindClass("android.R");
//global variables
var newvariabletext=" --- create a new variable --- ";
var filtertext=" --- filter variables --- ";
var vars;
var names;
var filter="";
//starts
show();
function show(){
LL.save();//save to force the file to be updated
var fullvars=JSON.parse(read("data/data/net.pierrox.lightning_launcher_extreme/files/variables")).v;//reads the content of the file
if(fullvars==null) fullvars=[];
//names=vars.v==null?[]:vars.v.map(function(a){return a.n+": '"+a.v+"'"});//extracts the variable names, if any
names=[];
vars=[]
for(var t=0;t<fullvars.length;++t){
var val=fullvars[t];
if(val.n.indexOf(filter)!=-1){
names.push(val.n+": '"+val.v+"'");
vars.push(val);
}
}
names.push(filter!=""?" --- Filter: "+filter+" ---":filtertext);//adds the 'filter variables' entry
names.push(newvariabletext);//adds the 'create variable' entry
list(names,clicked,"Choose a variable, or create a new one");//shows the list
}
//when clicked an element
function clicked(dialog,which){
if(which==names.length-1){
//the 'add a variable' entry chosen
addvariable();
}else if(which==names.length-2){
setFilter();
}else{
//a variable chosen
editvariable(vars[which]);
}
setTimeout(show,0);//shows the list again. On a timeout so the startActivity() is correctly launched before
}
//editing a variable
function editvariable(variable){
var name=variable.n;
//gets it's type
var llvar=LL.getVariables();
var type=llvar.getType(variable.n);
/*
//gets its value
var oldv;
switch(type){
case "FLOAT": oldv=llvar.getFloat(name); break;
case "INTEGER": oldv=llvar.getInteger(name); break;
case "BOOLEAN": oldv=llvar.getBoolean(name); break;
default: oldv=llvar.getString(name);
}
*/
//gets its value
var oldv=variable.v//vars.v.filter(function(obj){return obj.n==name})[0].v;
//asks for a new value
var newv=prompt(name+" ("+type+")",oldv);
if(newv==null){
//cancelled. delete?
if(confirm("Do you want to delete this variable?"))llvar.edit().setString(name,null).commit();
return;
}
//update the value
lightningcall(name,newv);
}
//adding a variable
function addvariable(){
var name="";
do{
//ask for a not-used name
name=prompt("Name of the variable",name);
}while(names.indexOf(name)!=-1&& !confirm("This variable name is already used, do you want to continue? (will be overwritten)"));
if(name==null)return;//cancelled
//asks for the value
var value=prompt("Value of the variable '"+name+"'","");
if(value==null)return;//cancelled
//create the variable
lightningcall(name,value);
}
//calls lightning action 'set a variable'
function lightningcall(name,value){
var intent=new Intent.getIntent("#Intent;component=net.pierrox.lightning_launcher_extreme/net.pierrox.lightning_launcher.activities.Dashboard;i.a=41;end");//the base intent
intent.putExtra("d",name+"/"+value);//the extra data
LL.startActivity(intent);
}
//sets the filter variable, used to filter entries
function setFilter(){
var newfilter=prompt("Show only names containing:\n(empty to disable the filter)",filter);
if(newfilter!=null)filter=newfilter;
}
//function to display a List in a Popup, where the user can select one item. Taken from Lukas Morawietz's Multi tool script
function list(items,onClickFunction,title){
var builder=new AlertDialog.Builder(new ContextThemeWrapper(LL.getContext(), R.style.Theme_DeviceDefault));
var listener=new DialogInterface.OnClickListener()
{
onClick:function(dialog,which)
{
setTimeout(function(){onClickFunction(dialog,which);},0);
}
}
builder.setItems(items,listener);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.cancel();}});//it has a Cancel Button
builder.show();
}
function read(filePath){
var file=new File(filePath);
var r=new BufferedReader(new FileReader(file));
var s="";
var l;
while((l=r.readLine())!=null)s+=(l+"\n");
return s.substring(0, s.length - 1);
}
//Flags: app item
//Name: [tool]Dynamic editor
var textColor=0xffffffff;
var tag="dynamiceditor";
//classes
LL.bindClass("android.widget.EditText");
LL.bindClass("android.text.TextWatcher");
LL.bindClass("android.app.AlertDialog.Builder");
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface.OnClickListener");
LL.bindClass("android.content.DialogInterface");
//vars
var cntx=LL.getContext();
var it;
var v;
var e;
//to detect when the script is run from the creation script
try{typeof item}catch(e){
return returnview();
}
//from event
e=LL.getEvent();
var source=e.getSource();
if(source=="MENU_APP"){
addview();
return
}
it=e.getItem();
v=it.getView();
if(source=="MENU_ITEM")askscript();
if(source=="I_RESUMED")updateview();
//checks if there is a saved script
function checkscript(){
var name=it.getTag(tag);
if(name==null||LL.getScriptByName(name)==null){
if(e!=null)Android.makeNewToast("Script not set or not found. Please run the script from the view",false).show();
return false;
}
return true;
}
//prompts a list of the script to choose from
function askscript(){
var list=LL.getAllScriptMatching(Script.FLAG_ALL);
var scripts=[];
for(var t=0;t<list.getLength();++t)scripts[t]=list.getAt(t).getName();
var builder = new AlertDialog.Builder(cntx);
builder.setTitle("Choose a script");
builder.setItems(scripts, new DialogInterface.OnClickListener() {onClick: function(dialog,item) {
dialog.dismiss();
it.setTag(tag,scripts[item]);
updateview();
}
});
builder.setNegativeButton("Close",null)
builder.show();
}
function updatescript(){
//replace the script text with the view text
if(!checkscript())return;
LL.getScriptByName(it.getTag(tag)).setText(v.getText());
}
function updateview(){
//replace the view text with the script text
if(!checkscript())return;
v.setText(LL.getScriptByName(it.getTag(tag)).getText());
}
function returnview(){
//returns the view
it=item;
item.setVerticalGrab(true);
v=new EditText(cntx);
v.setTextColor(textColor);
v.setGravity(80);//BOTTOM
v.setText("run the script from this view");
v.addTextChangedListener(new TextWatcher({afterTextChanged:function(s){updatescript()},
beforeTextChanged:function(s, start,count,after){},
onTextChanged:function(s,start,before,count){}
}));
updateview();
return v;
}
function addview(){
//adds directly a custom view
it=e.getContainer().addCustomView(e.getTouchX(),e.getTouchY());
var thisid=""+LL.getCurrentScript().getId();
var prop=it.getProperties().edit()
prop.setString("v.onCreate",thisid)
prop.setEventHandler("i.resumed",EventHandler.RUN_SCRIPT,thisid)
prop.getBox("i.box").setColor("c", "s", 0);
prop.commit();
v=it.getView();
askscript();
}
//Flags: app item
//Name: [wiki] save layout
var defvelocity = 0.2;//The default velocity. The bigger, the faster (between (0,1] warning: outside that range it can crash)
var frecuency = 60;//ticks per second [Recommended 60] (set to 0 for fastest possible, in case you have a lot of items)
/*
Script made by TrianguloY you can contact me in Google+
This script will move the items in free mode to the position they had when saved.
To save the position just place the items where you want in free mode and run this script from the scripts menu.
The data is saved in the tag of the item/container.
modified: no, original script
(change this if you want to modify something and publish it)
*/
var debug = false;
//vars
var event = LL.getEvent();
var cont = event.getContainer();
var item = event.getItem();
var tagged=item||cont;
var source=event.getSource();
var tag = tagged.getTag();
var data=JSON.parse(tag);
//save mode
if(source=="MENU_ITEM" || source=="MENU_APP" || tag==undefined || data[0]==undefined || data[0][0]!='save layout'){
save();
return;
}
//token to stop if another instance is running
var sessiontoken;
do{
sessiontoken=""+Math.random();
}while(sessiontoken==LL.getScriptTag());
LL.setScriptTag(sessiontoken);
var velocity = data[0][1]||defvelocity;
//execute in each item
for(var i=data.length-1;i>0;--i){
var item= LL.getItemById(data[i][0]);
//move the item to their position if in free mode
if(item!=null && item.getCell()==null) {
if(debug)item.setLabel("@"+item.getLabel());
move(item, data[i]);
}
}
return;
//save function
function save(){
//initial checks
var vel=defvelocity;
if(data!=null && data[0]!=null && data[0][0]!='save layout') {
alert("Diferent tag found:\n"+data);
}else{
if(data!=null && data[0]!=null)vel=data[0][1];
}
var vel=prompt("Save?\n Velocity: the bigger the faster\nbetween (0,1]",vel);
if(vel==null)return;
vel=vel>1?1:vel<=0?defvelocity:vel;
//data storing procces
data=[];
data[0]=["save layout",vel];
var i = 1;
var items = cont.getItems();
for(var j=items.getLength()-1;j>=0;--j){
//save the data of each item
var t = items.getAt(j);
//avoid grid items
if(t.getCell()!=null)continue;
data[i]=[];//data of the item (in rows to see where each one is stored)
data[i][1]=t.getPositionX();
data[i][2]=t.getPositionY();
data[i][3]=t.getScaleX();
data[i][4]=t.getScaleY();
data[i][5]=t.getWidth();
data[i][6]=t.getHeight();
data[i][7]=t.getRotation();
//convert to the center of the item
var c=center(data[i]);
data[i][1]+=c[0];
data[i][2]+=c[1];
data[i][0]=t.getId();
++i;
};
//final save
tagged.setTag(JSON.stringify(data));
Android.makeNewToast("Saved "+(i-1)+" item's data in "+tagged,true).show();
}
//custom lerp. It moves the item a bit and repeat, stops when finish, when LL is not active or when another instance of the script runs
function move(item,dat){
//another script is running
if( sessiontoken!=LL.getScriptTag()){return;}
//actual data
var now = [
0,
item.getPositionX(),
item.getPositionY(),
item.getScaleX(),
item.getScaleY(),
item.getWidth(),
item.getHeight(),
item.getRotation()
];
var n=center(now);
now[1]+=n[0];
now[2]+=n[1];
//calculate the next step
var cut=[0,0.5,0.5,0.01,0.01,1,1,0.99];
var step = [];
var flag = "";
for(var j=dat.length-1;j>0;--j){
step[j]=dat[j]-now[j];
if(Math.abs(step[j])>cut[j]){
flag+=j;
if (cut[j]==1){
step[j]=now[j]+(step[j]>0?Math.max(step[j]*velocity,cut[j]):Math.min(step[j]*velocity,-cut[j]));
}else step[j]=now[j]+step[j]*velocity;
}else step[j]=dat[j];
}
//if nothing changed or LL paused
if( flag=="" || LL.isPaused()){
item.setScale(dat[3],dat[4]);
item.setSize(dat[5],dat[6]);
item.setRotation(dat[7]);
var d = center(dat);
item.setPosition(dat[1]-d[0],dat[2]-d[1]);
if(debug)item.setLabel(item.getLabel());
return;
}
if(debug)item.setLabel(flag+"@"+item.getLabel());
//sets the next step and repeat
item.setSize(step[5],step[6]);
item.setScale(step[3],step[4]);
item.setRotation(step[7]);
var s=center(step);
item.setPosition(step[1]-s[0],step[2]-s[1]);
velocity=(1+999*velocity)/1000;
setTimeout(function(){ move(item,dat);},frecuency==0?0:1000/frecuency);
}
//custom function to get the center of the item d=[,,,sizx,sizy,scax,scay,rot]
function center(d){
var c=[];
var r=d[7]*Math.PI/180; c[0]=Math.abs(d[4]*d[6]*Math.sin(r))/2+Math.abs(d[3]*d[5]*Math.cos(r))/2;
c[1]=Math.abs(d[3]*d[5]*Math.sin(r))/2+Math.abs(d[4]*d[6]*Math.cos(r))/2;
return c;
}
//Flags: custom
//Name: [zz]OnLoad
var now=LL.getEvent().getDate();
var old=LL.getCurrentScript().getTag();
LL.getCurrentScript().setTag(now);
if(now-old<7*24*60*60*1000) return;
Android.makeNewToast("onLoad"+Math.random(),true).show();
LL.runScript("[tool] scripts backup",null);
return
LL.bindClass("android.view.WindowManager");
LL.bindClass("android.transition.Explode");
LL.bindClass("android.R");
LL.getContext().setTheme(R.style.Theme_Holo);
//LL.getContext().getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
// inside your activity (if you did not enable transitions in your theme)
//LL.getContext().getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an exit transition
//LL.getContext().getWindow().setEnterTransition(new Explode());
//Flags:
//Name: Custom view
LL.bindClass("android.view.SurfaceView");
var view = new SurfaceView(LL.getContext());
return view
//Flags: app item
//Name: lagrange check
//Flags: app item
//Name: lagrange check
var extrapolate=false;//set this to true to extrapolate
//clases
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.content.DialogInterface");
//vars
var event=LL.getEvent();
var item=event.getItem();
var cont=event.getContainer();
var source=event.getSource();
//the list of parameters
var parameters = ["Position X","Position Y","Rotation","Scale X","Scale Y","Alpha","Width","Height"];
//vars related to the interpolation data
var data=JSON.parse(cont.getTag("intpol"))||{};
var d;
var page;
var flags=[];
if(source=="C_POSITION_CHANGED"){
//interpolate
apply();
}else if(item!=null){
//apply settings for the item
//create the object that will contain the data
d=(data[item.getName()])||{flags:[],lagrange:[],pages:[]};
while(d.flags.length<parameters.length)d.flags.push(false);
while(d.pages.length<parameters.length)d.pages.push({});
//the list of properties
for(var t in d.flags)flags[t]=d.flags[t];
choose();
}else{
//no item
alert("run the script from an item");
//prompt("",cont.getTag("intpol"));//for debug
}
function choose(){
//shows the dialogs
//asks for the page (selected: current)
var w=cont.getWidth();
var x=cont.getPositionX();
var b=cont.getBoundingBox();
page=w*LL.pickNumericValue("save for which page? (horizontally, 0 is the main page)", Math.round(x/w), "FLOAT", Math.floor(b.getLeft()/w)-1, Math.ceil(b.getRight()/w), 1, "page");
if(page==null)return;
//parameters
var builder=new AlertDialog.Builder(LL.getContext());
builder.setTitle("Choose parameters to save/remove");
builder.setMultiChoiceItems(parameters,flags,new DialogInterface.OnMultiChoiceClickListener(){onClick:function(dialog,which,checked){flags[which]=checked;}});
builder.setNegativeButton("Cancel",null);
builder.setPositiveButton("Save",new DialogInterface.OnClickListener(){onClick:save});
builder.setNeutralButton("Remove",new DialogInterface.OnClickListener(){onClick:remove});
builder.create().show();
}
function save(){
//save the data of the selected parameters
if(flags[0])d.pages[0][page]=item.getPositionX();
if(flags[1])d.pages[1][page]=item.getPositionY();
if(flags[2])d.pages[2][page]=item.getRotation();
if(flags[3])d.pages[3][page]=item.getScaleX();
if(flags[4])d.pages[4][page]=item.getScaleY();
if(flags[5])d.pages[5][page]=item.getProperties().getInteger("i.alpha");
if(flags[6])d.pages[6][page]=item.getWidth();
if(flags[7])d.pages[7][page]=item.getHeight();
update();
}
function update(){
//create the polynomial for each animated parameter
for(var t=0;t<d.flags.length;++t){
difdiv(d.pages[t],Object.keys(d.pages[t]).sort(function(a,b){return parseInt(a)-parseInt(b);}),t);
}
//save the data
var name=item.getName();
if(name==null){
var p=0;
do{name="auto-name "+ p++;}while(cont.getItemByName(name)!=null);
item.setName(name);
}
data[name]=d;
cont.setTag("intpol",JSON.stringify(data));
}
function remove(){
//removed the data of the selected parameters
for(var t=0;t<flags.length;++t){
if(flags[t]) delete d.pages[t][page];
}
update();
}
function apply(){
//sets the data when moving the desktop
var ids=Object.keys(data);
for(var t=0;t<ids.length;++t){
var item=cont.getItemByName(ids[t]);
if(item==null){
//if a saved item is not found, removes the data of that item
delete data[ids[t]];
cont.setTag("intpol",JSON.stringify(data));
continue;
}
//apply the interpolation
d=data[ids[t]];
if(d.flags[6]||d.flags[7])item.setSize(d.flags[6]?intpol(6):item.getWidth(),d.flags[7]?intpol(7):item.getHeight());
if(d.flags[2])item.setRotation(intpol(2));
if(d.flags[3]||d.flags[4])item.setScale(d.flags[3]?intpol(3):item.getScaleX(),d.flags[4]?intpol(4):item.getScaleY());
if(d.flags[0]||d.flags[1])item.setPosition(d.flags[0]?intpol(0):item.getPositionX(),d.flags[1]?intpol(1):item.getPositionY());
if(d.flags[5])item.getProperties().edit().setInteger("i.alpha",intpol(5,0,255)).commit();
}
}
function intpol(prop,min,max){
//fixed function: based of the saved polynomial returns the value
var c=cont.getPositionX();
var index=d.lagrange[prop];
var n=index[0].length-1;
if(!extrapolate){
if(c>index[1][n]) return d.pages[prop][index[1][n]];
if(c<index[1][0]) return d.pages[prop][index[1][0]];
}
var out=index[0][n];
for(var t=n-1;t>=0;--t){
out=index[0][t]+(c-index[1][t])*out;
}
if(min!=null&&out<min)return min;
if(max!=null&&out>max)return max;
return out;
}
function difdiv(values,nodes,prop){
//fixed function: calculates the data of the interpolation polynomial based on the saved data
var y=[[]];
var n=nodes.length;
if(n<=0){
delete d.lagrange[prop];
d.flags[prop]=false;
}else{
d.flags[prop]=true;
}
for(var t=0;t<n;++t){
y[t]=[];
y[t][0]=values[nodes[t]];
}
for(var k=1;k<n;++k)for(var i=0;i<n-k;++i){
y[i][k]=(y[i+1][k-1]-y[i][k-1])/(nodes[i+k]-nodes[i]);
}
if(d.lagrange[prop]==null)d.lagrange[prop]=[];
d.lagrange[prop][0]=y[0];
d.lagrange[prop][1]=nodes;
}
/*
data:{
<name>:{
flags:[,] //will animate or not
lagrange:[property]:{
[0]: d of the polynomial
[1]: nodes
}
pages:[property]{
[page] value of that property at the current page
}
}
}
*/
//Flags:
//Name: lukas debug gesture
LL.bindClass("java.lang.Class");
LL.bindClass("dalvik.system.PathClassLoader");
var c=LL.getContext().createPackageContext("com.faendir.lightning_launcher.multitool",2);
var apk = c.getPackageManager().getApplicationInfo("com.faendir.lightning_launcher.multitool",0).sourceDir;
var clsLoader=new PathClassLoader(apk,PathClassLoader.getSystemClassLoader());
var cls=Class.forName("com.faendir.lightning_launcher.multitool.gesture.LightningGestureView",true,clsLoader);
var v=cls.getConstructors()[0].newInstance(c);
item.setHorizontalGrab(true);
item.setVerticalGrab(true);
return v;
//Flags: custom
//Name: ScriptManager
var intent = new Intent("android.intent.action.View");
intent.setClassName("com.faendir.lightning_launcher.multitool","com.faendir.lightning_launcher.multitool.MainActivity");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
var s = LL.getAllScriptMatching(Script.FLAG_ALL);
var list = [];
for(var i = 0; i < s.length; i++){
var script = s.getAt(i);
var flags = 0;
if(script.hasFlag(Script.FLAG_DISABLED)) flags += Script.FLAG_DISABLED;
if(script.hasFlag(Script.FLAG_APP_MENU)) flags += Script.FLAG_APP_MENU;
if(script.hasFlag(Script.FLAG_ITEM_MENU)) flags += Script.FLAG_ITEM_MENU;
if(script.hasFlag(Script.FLAG_CUSTOM_MENU)) flags += Script.FLAG_CUSTOM_MENU;
list.push({id:script.getId(), name:script.getName(), code:script.getText(), flags:flags});
}
intent.putExtra("scripts",JSON.stringify(list));
var data = LL.getEvent().getData();
if(data != null && data != ""){
var transfer = JSON.parse(data);
switch(transfer.request){
case "RENAME":
var script = LL.getScriptById(transfer.script.id);
if(script!=null) script.setName(transfer.script.name);
break;
case "DELETE":
var script = LL.getScriptById(transfer.script.id);
if(script!=null) LL.deleteScript(script);
break;
case "RESTORE":
var script = LL.getScriptByName(transfer.script.name);
if(script!=null){
LL.deleteScript(script);
}
LL.createScript(transfer.script.name,transfer.script.code,transfer.script.flags);
break;
case "SET_CODE":
var script = LL.getScriptById(transfer.script.id);
if(script!=null) script.setText(transfer.script.code);
break;
}
}
LL.startActivity(intent);
//Flags:
//Name: Sketch / button handler
/*
Pierre Hébert - Sketch - 2014
This software is provided as is. Public domain.
You are free to use, duplicate and modify it without restriction.
*/
var item = LL.getEvent().getItem();
var drawing = item.getParent().getItemByLabel("drawing");
// this handler is associated with several buttons, check the button label to see what to do
var label = item.getLabel();
var longclick= LL.getEvent().getSource()=="I_LONG_CLICK";
switch(label){
case "color":
var color = item.getProperties().getBox("i.box").getColor("c", "n");
if(longclick){
var newcolor=LL.pickColor("New color",color,true);
if(newcolor==null)return;
var prop=item.getProperties().edit();
prop.getBox("i.box").setColor("c", "n",newcolor);
prop.commit();
color=newcolor;
}
drawing.setTag("color",color);
drawing.setTag("mode","");
break;
case "big":
var tag= drawing.getTag("mode")+"size";
var h=parseInt(drawing.getTag(tag));
if(isNaN(h))h=5;
h++;
drawing.setTag(tag,h);
break;
case "small":
var tag= drawing.getTag("mode")+"size";
var h=parseInt(drawing.getTag(tag));
if(isNaN(h))h=5;
h=Math.max(h-1,1);
drawing.setTag(tag,h);
break;
case "rubber":
drawing.setTag("mode","rubber");
break;
case "normal":
drawing.setTag("mode","");
break;
case "back":
var tag=drawing.getTag("back");
if(longclick){
drawing.setTag("back", tag!="disabled" ? "disabled" : null);
item.getProperties().edit().setInteger("i.alpha", tag!="disabled" ? 125 : 255).commit();
return;
}
if(tag=="disabled"){
Android.makeNewToast("Back is disabled. Long click to activate (it may slow the painting)", true).show();
return;
}
var p = new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
var n=drawing.getBoxBackground("n");
var s=drawing.getBoxBackground("s");
var f=drawing.getBoxBackground("f");
if(tag=="saved"){
n.draw().drawBitmap(f.getBitmap(),0,0,p);
f.draw().drawBitmap(s.getBitmap(),0,0,p);
s.draw().drawBitmap(n.getBitmap(),0,0,p);
n.update();
}
return;
break;
case "clear":
var pclear = new Paint();
pclear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
var p = new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
if(longclick&&confirm("Reset the sketch?")){
drawing.setTag("back",null);
drawing.setBoxBackground(LL.createImage(drawing.getWidth(),drawing.getHeight()),"n", true);
drawing.setBoxBackground(LL.createImage(drawing.getWidth(),drawing.getHeight()),"s", true);
drawing.setBoxBackground(LL.createImage(drawing.getWidth(),drawing.getHeight()),"f", true);
var preview= item.getParent().getItemByLabel("preview");
preview.setBoxBackground(LL.createImage(preview.getWidth(),preview.getHeight()),"n", true);
}
var backcolor=drawing.getTag("background");
if(backcolor==null)backcolor=0xff000000;
if(longclick){
backcolor=LL.pickColor("BackgroundColor",backcolor,true);
if(backcolor==null) return;
}
drawing.setTag("background",backcolor);
var n = drawing.getBoxBackground("n");
var s = drawing.getBoxBackground("s");
var f = drawing.getBoxBackground("f");
f.draw().drawBitmap(s.getBitmap(),0,0,p);
n.draw().drawPaint(pclear);
n.draw().drawColor(backcolor);
n.update();
s.draw().drawPaint(pclear);
s.draw().drawColor(backcolor);
break;
}
//update preview
var preview= item.getParent().getItemByLabel("preview");
var mode=drawing.getTag("mode");
var size=drawing.getTag(mode+"size");
var color=parseInt(drawing.getTag("color"));
var background=parseInt(drawing.getTag("background"));
var pclear = new Paint();
pclear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
var image=preview.getBoxBackground("n");
var canvas=image.draw();
canvas.drawPaint(pclear);
var paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(size);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
if(mode=="rubber"){
canvas.drawColor(0xffffffff ^ background);
paint.setColor(background);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
}else{
canvas.drawColor(background);
paint.setColor(color);
}
canvas.drawLine(item.getWidth()/3,item.getHeight()/3,item.getWidth()*2/3,item.getHeight()*2/3,paint);
/*var path=new Path();
var sw=item.getWidth()/2;
var sh=item.getHeight()/2;
path.moveTo(sw*Math.random(),sh*Math.random());
path.lineTo(sw+sw*Math.random(),sh*Math.random());
path.lineTo(sw*Math.random(),sh+sh*Math.random());
path.lineTo(sw+sw*Math.random(),sh+sh*Math.random());
canvas.drawPath(path,paint);
*/
image.update();
image.save();
preview.setBoxBackground(image,"n",true);
//Flags:
//Name: Sketch / touch handler
/*
Pierre Hébert - Sketch - 2014
This software is provided as is. Public domain.
You are free to use, duplicate and modify it without restriction.
*/
var x = event.getX();
var y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
prev_x = x;
prev_y = y;
gete
var color = parseInt(item.getTag("color"));
var rubbercolor = parseInt(item.getTag("background"));
if(isNaN(color)) color = 0xff000000;
if(isNaN(rubbercolor)) rubbercolor = 0x00000000;
var size=parseInt(item.getTag("size"));
var rubbersize=parseInt(item.getTag("rubbersize"));
if(isNaN(size)) size = 5;
if(isNaN(rubbersize)) rubbersize = 5;
var mode = item.getTag("mode");
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
if(mode=="rubber"){
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
paint.setColor(rubbercolor);
paint.setStrokeWidth(rubbersize);
}else{
paint.setColor(color);
paint.setStrokeWidth(size);
}
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
image = item.getBoxBackground("n");
canvas = image.draw();
//canvas.scale( image.getWidth() / item.getWidth(), image.getHeight() / item.getHeight());
break;
case MotionEvent.ACTION_MOVE:
canvas.drawLine(prev_x, prev_y, x, y, paint);
prev_x = x;
prev_y = y;
image.update();
break;
case MotionEvent.ACTION_UP:
image.update();
if(item.getTag("back")!="disabled"){
var p = new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
item.getBoxBackground("f").draw().drawBitmap(item.getBoxBackground("s").getBitmap(),0,0,p);
item.getBoxBackground("s").draw().drawBitmap(item.getBoxBackground("n").getBitmap(),0,0,p);
item.setTag("back","saved");
}
paint = null;
canvas = null;
break;
}
return true;
//Flags: app item
//Name: test [tool] Fast Run Tool
/*
Script: Fast Run Tool
Original by: TrianguloY
This script is provided as is. Public domain.
You are free to use, duplicate and modify it without restriction.
If you want to share it (modified or not) please don't change the first part of this header.
Modified by: <unmodified>
*/
/*config*/
var fastRunTool_runData = true;//enable this to run passed scripts as data when using a shortcut
var fastRunTool_reminder = true;//whether to show or not the previous input in the alert description
/*end of config*/
/*Available vars*/
var e = LL.getEvent();//event
var c = e.getContainer();//container
var i = e.getItem();//item
var cntx = LL.getContext();//context
/*end of available vars*/
/*available functions*/
//helper function to show a toast in a shorter way
function toast(say){
if(say==null)say="null";
Android.makeNewToast(say,false).show();
}
//helper function to bind a class in a shorter way
function bind(class){
return LL.bindClass(class);
}
//deprecated. sets and returns the item default tag
function iTag(setnew){
if(setnew!=undefined){
if(setnew=='null')setnew=null; i.setTag(setnew);
}
return i.getTag();
}
//deprecated. sets and returns the container default tag
function cTag(setnew){
if(setnew!=undefined){
if(setnew=='null')setnew=null; c.setTag(setnew);
}
return c.getTag();
}
//evaluates the func function for each item in container (c if null)
function foreach(func,container){
if(container==null)container=c;
var items=container.getItems();
for(var t=0;t<items.getLength();++t)func(items.getAt(t));
}
//this returns a string with the properties/methods of the object.
//optionally will only return those with 'search' in it
function objects(obj,search){
if(obj==""||obj==null) return "";//no valid object
var keys=Object.keys(obj);//magic line ;)
keys.sort();
var text="";//the output
for(t in keys){
var key=keys[t];
var prop;
try{
prop=""+obj[key];//when calling that key
}catch(e){
prop=""+e;//there were an error calling the key
}
if(
search!=null
&&
key.toLowerCase().indexOf(search.toLowerCase())==-1
&&
prop.toLowerCase().indexOf(search.toLowerCase())==-1
)continue;//searching not found
text+=key+" : "+prop+"\n";
if(prop[prop.length-1]!="\n")text+="\n";
}
return text;
}
/*end of available functions*/
//run from data
var fastRunTool_datatorun=LL.getEvent().getData();
if(!fastRunTool_runData && fastRunTool_datatorun!=null){
Android.makeNewToast("Running scripts from shortcuts is disabled. Change it in the script settings if you want to",false).show();
return;
}
if(fastRunTool_datatorun!=null&&fastRunTool_datatorun!=""){
eval("function fastRunTool(){\n"+fastRunTool_datatorun+"\n}");
fastRunTool();
return;
}
//if no data to run, use the inputted one
if(fastRunTool_datatorun==""){
eval("function fastRunTool(){\n"+LL.getScriptTag()+"\n}");
fastRunTool();
return;
}
//normal run
var fastRunTool_repeat=true;//will allow to run again after an error
while(fastRunTool_repeat){fastRunTool_repeat=false;
var fastRunTool_text = LL.getScriptTag() || "";
var fastRunTool_description =
"Vars: e-event, cntx-context"+
(c!=null? ", c-container":", [no container]")+
(i!=null? ", i-item":", [no item]")+
"\n"+
"Functions: toast(String)"+
", boolean bind(String)"+
//(c!=null ? ", String cTag(String)":"")+
//(i!=null ? ", String iTag(String)":"")+
", void foreach(function(item),{container (c)})"+
", String objects(Object,{search})"+
(fastRunTool_reminder ? "\n\nPrevious input:\n"+
fastRunTool_text+
"\n_____________________________________" : "");
//Change this description if you want
//this asks for the code to run
var fastRunTool_out = prompt(fastRunTool_description,fastRunTool_text);
if(fastRunTool_out==null) return;//cancel
LL.setScriptTag(fastRunTool_out);//save
var fastRunTool_torun=fastRunTool_out;
//gets the last line.
var fastRunTool_last=fastRunTool_out.lastIndexOf("\n")+1;//
var fastRunTool_line=fastRunTool_out.substr(fastRunTool_last);
//If no ';' , '}' or '//' found encapsulate it inside a prompt
if(fastRunTool_line.search(/(\;|\}|\/\/)/)==-1) fastRunTool_torun=fastRunTool_out.substr(0,fastRunTool_last)+"prompt('»"+fastRunTool_line.replace(/'/g,"\\'")+"«',fastRunTool_toStringFormatted("+fastRunTool_line+"));";
//evaluates the code
fastRunTool_torun="function fastRunTool(){"+fastRunTool_torun+"\n}";
try{
eval(fastRunTool_torun);
fastRunTool();
}catch(fastRunTool_error){
//error found. Showing and repeating
fastRunTool_repeat=prompt(fastRunTool_out.split("\n").map(function(v,i,a){return ":"+(i+1)+":"+v;}).join("\n"),fastRunTool_error)!=null;
}
}//end of repeat
//custom functions
//returns the input as string or as a formatted string if already
function fastRunTool_toStringFormatted(a){
return typeof a!="string" ? ""+a : '"'+a.replace(/"/g,'\\"')+'"' ;
}
//Flags: app item
//Name: zzz test - MultiTool
//Created by Lukas Morawietz in collaboration with TrianguloY
//import java classes
LL.bindClass("android.app.AlertDialog");
LL.bindClass("android.app.ProgressDialog");
LL.bindClass("android.content.DialogInterface");
LL.bindClass("android.os.Environment");
LL.bindClass("android.R");
LL.bindClass("android.widget.ExpandableListView");
LL.bindClass("android.widget.ImageView");
LL.bindClass("android.widget.LinearLayout");
LL.bindClass("android.widget.ListView");
LL.bindClass("android.widget.NumberPicker");
LL.bindClass("android.widget.SimpleAdapter");
LL.bindClass("android.widget.SimpleExpandableListAdapter");
LL.bindClass("android.widget.ScrollView");
LL.bindClass("android.widget.TextView");
LL.bindClass("java.io.File");
LL.bindClass("java.io.BufferedReader");
LL.bindClass("java.io.FileReader");
LL.bindClass("java.io.FileWriter");
LL.bindClass("java.util.HashMap");
LL.bindClass("java.util.ArrayList");
var hasItem=(LL.getEvent().getItem()!=null);
//define Strings to display
var title="What do you want to do?";
var items=[]
var info=["Information",[]];
info[1].push("Event");
info[1].push("Container");
if(hasItem){
info[1].push("Item");
info[1].push("Intent");
info[1].push("Icon");
}
var itemUtils=["Item Utilities",[]];
itemUtils[1].push("Attach/Detach all Items");
itemUtils[1].push("Resize all detached Items");
itemUtils[1].push("Delete all Items");
itemUtils[1].push("Move Pages");
var other = ["Other",[]];
other[1].push("Reset Tag");
other[1].push("Reset Tool");
other[1].push("Save changes");
other[1].push("Delete recent app history");
items.push(info);
items.push(itemUtils);
items.push(other);
//normal run
if(typeof resultCode==='undefined') expandableList(items,mainOnClick,title);
//user has selected a file to import
else import_handleInput();
//handle user selection
function mainOnClick(groupPosition,childPosition){
switch(groupPosition){
case 0://Information
switch(childPosition){
case 0://Event related
eventData();
break;
case 1://container related
containerData()
break;
case 2://item related
itemData();
break;
case 3://intent
intentData();
break;
case 4://icon
iconData();
break;
}
break;
case 1://item utilities
switch(childPosition){
case 0://Attach/Detach all items
attachDetachAll();
break;
case 1://resize detached items
resizeAllDetached();
break;
case 2://delete items
deleteAll();
break;
case 3://move pages
movePages();
break;
}
break;
case 2://other
switch(childPosition){
case 0://reset Tag
resetTags();
break;
case 1://reset tool by trianguloY, ask him how it works :D
resetTool();
break;
case 2:
saveLayout();
break;
case 3:
resetRecents();
break;
}
break;
}
}
function eventData(){
var e=LL.getEvent();
try{ //test if event contains touch data
e.getTouchScreenX();
var ok=true;
}
catch(Exception){
var ok=false;
}
text("Source: "+e.getSource()+"\nDate: "+e.getDate()+"\nContainer: "+e.getContainer()+"\nItem: "+e.getItem()+(ok?("\nTouch: "+e.getTouchX()+","+e.getTouchY()+"\nTouch (Screen): "+e.getTouchScreenX()+","+e.getTouchScreenY()):""),"Event Information");
}
function containerData(){
var c=LL.getEvent().getContainer();
var t=c.getType();//Differentiate between Desktop and other containers
//read Tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+c.getId()+"/conf");
var data=JSON.parse(s);
var tags="Default: "+c.getTag();
for(property in data.tags)
tags+="\n"+property+": "+data.tags[property];
text("Type: "+t+"\nName/Label: "+(t=="Desktop"?c.getName():c.getOpener().getLabel())+"\nID: "+c.getId()+"\nSize: "+c.getWidth()+","+c.getHeight()+"\nBoundingbox: "+c.getBoundingBox()+"\nCell Size: "+c.getCellWidth()+","+c.getCellHeight()+"\nCurrent Position: "+c.getPositionX()+","+c.getPositionY()+"\nCurrent Scale: "+c.getPositionScale()+"\nTags: "+tags+"\nItems: "+c.getItems(),"Container Information");
}
function itemData(){
var i=LL.getEvent().getItem();if(i==null)//check if event contains item
text("no item found","Error 5");
//read tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+LL.getEvent().getContainer().getId()+"/items");
var all=JSON.parse(s).i;
var x;
var item;
for(x=0;x<all.length;x++){
item=all[x];
if(item.b==i.getId())break;
}
if(x==all.length){
text("Can't find Tags","Error 6");
return;
}
var tags="Default: "+i.getTag();
for(property in item.an){
if(property=="_")continue;
tags+="\n"+property+": "+item.an[property];
}
text("Label: "+i.getLabel()+"\nType: "+i.getType()+"\nID: "+i.getId()+"\nSize: "+i.getWidth()+","+i.getHeight()+"\nPosition: "+i.getPositionX()+","+i.getPositionY()+"\nScale: "+i.getScaleX()+","+i.getScaleY()+"\nAngle: "+i.getRotation()+"\nCenter: "+center(i)+((i.getType()=="Shortcut"||i.getType()=="Folder")?"\nIntent:"+i.getIntent():"")+"\nTags: "+tags,"Item Information");
}
function intentData(){
it=LL.getEvent().getItem();
if(it==null || item.getType()!="Shortcut")text("No Intent found.","Error 1");
else text("Intent: "+it.getIntent()+"\nExtras: "+it.getIntent().getExtras(),"Intent Information");
}
function iconData(){
it=LL.getEvent().getItem();
//create view structure
var root=new LinearLayout(LL.getContext());
root.setOrientation(LinearLayout.VERTICAL);
//check for all kinds of images in this item and add them to the view if there are any
addImageIfNotNull(root,it.getBoxBackground("n"),"Normal Box Background");
addImageIfNotNull(root,it.getBoxBackground("s"),"Selected Box Background");
addImageIfNotNull(root,it.getBoxBackground("f"),"Focused Box Background");
if(it.getType()=="Shortcut"){
addImageIfNotNull(root,image=it.getDefaultIcon(),"Default Icon");
addImageIfNotNull(root,image=it.getCustomIcon(),"Custom Icon");
}
if(root.getChildCount()>0){ //at least one image found
var scroll=new ScrollView(LL.getContext());
scroll.addView(root);
customDialog(scroll,"Icon");
}
else Android.makeNewToast("No Image Data available",true).show(); //no image found
}
function attachDetachAll(){
var items=LL.getEvent().getContainer().getItems();
var attachDetach = function(toGrid){
for(x=0;x<items.length;x++)
{
var i=items.getAt(x);
i.getProperties().edit().setBoolean("i.onGrid",toGrid).commit();
}
Android.makeNewToast("Done!",true).show();
}
var attach = function(){attachDetach(true);}
var detach = function(){attachDetach(false);}
chooser([function(){},attach,detach],["Cancel","Attach","Detach"],"Do you want to attach or detach all items?","MultiTool");
}
function resizeAllDetached(){
var linearLayout = new LinearLayout(LL.getContext());
var c = LL.getEvent().getContainer();
linearLayout.setOrientation(LinearLayout.VERTICAL);
var widthText = new TextView(LL.getContext());
widthText.setText("Width: ");
linearLayout.addView(widthText);
var widthPicker = new NumberPicker(LL.getContext());
widthPicker.setMinValue(1);
widthPicker.setMaxValue(9999);
widthPicker.setValue(c.getCellWidth());
linearLayout.addView(widthPicker);
var heightText = new TextView(LL.getContext());
heightText.setText("Height: ");
linearLayout.addView(heightText);
var heightPicker = new NumberPicker(LL.getContext());
heightPicker.setMinValue(1);
heightPicker.setMaxValue(9999);
heightPicker.setValue(c.getCellHeight());
linearLayout.addView(heightPicker);
var onClick = function(){
var s=[widthPicker.getValue(),heightPicker.getValue()];
var items=c.getItems();
for(var a=0;a<items.length;a++)
items.getAt(a).setSize(s[0],s[1]);
}
customConfirmDialog(linearLayout,"To which size?",onClick);
}
function deleteAll(){
var f = function(){
var c=LL.getEvent().getContainer();
var i=c.getItems();
for(a=0;a<i.length;a++)
c.removeItem(i.getAt(a));
}
chooser([function(){},f],["No","Yes"],"Are you sure?","Delete all items");
}
function movePages(){
var cont=LL.getEvent().getContainer();
var items=cont.getItems();
var cWidth=cont.getWidth();
var cHeight=cont.getHeight();
var cellsFloatX=cWidth/cont.getCellWidth();
var cellsFloatY=cHeight/cont.getCellHeight();
var cellsX=Math.round(cellsFloatX);
var cellsY=Math.round(cellsFloatY);
var f=function(){
try{
//page(s) selection
var s=prompt("Which page do you want to move? (* for all) input has to be x,y (e.g. *,* for all pages)","").split(",");
var move=JSON.parse("[\""+s[0]+"\",\""+s[1]+"\"]");
var done=true;
}
catch(Exception){
var done=false;
}
//check for valid input
if(!done||move==null||move[0]==null||(move[0]!="*"&&isNaN(parseInt(move[0])))||move[1]==null||(move[1]!="*"&&isNaN(parseInt(move[1])))){
Android.makeNewToast("Invalid input",true).show();
return;
}
//format to int if needed
if(move[0]!="*")move[0]=parseInt(move[0]);
if(move[1]!="*")move[1]=parseInt(move[1]);
try{
//user selection: destination
var dist=JSON.parse("["+prompt("How far do you want to move? input has to be x,y (e.g. 1,0 for one page right)","")+"]");
var done=true;
}
catch(Exception){
var done=false;
}
//check for valid input
if(!done||dist==null||dist[0]==null||isNaN(dist[0])||dist[1]==null||isNaN(dist[1])){
Android.makeNewToast("Invalid input",true).show();
return;
}
if(dist[0]==0&&dist[1]==0)return;//if nothing to do, do nothing :P
//do the movement
for(var i=items.getLength()-1;i>=0;--i){
var item=items.getAt(i);
var pos=[item.getPositionX(),item.getPositionY()];
//check if item should be moved
if((move[0]=="*" || (pos[0]>=cWidth*move[0] && pos[0]<cWidth*(move[0]+1))) && (move[1]=="*" || (pos[1]>=cHeight*move[1] && pos[1]<cHeight*(move[1]+1)))){
var prop=item.getProperties();
//handle pinned item
var xx=1,yy=1;
var pinMode=prop.getString("i.pinMode");
if(pinMode[0]=="X")xx=0;
if(pinMode.indexOf("Y")!=-1)yy=0;
//move it
if(prop.getBoolean("i.onGrid")){
var cell=item.getCell();
item.setCell(cell.getLeft()+cellsX*dist[0]*xx,cell.getTop()+cellsY*dist[1]*yy,cell.getRight()+cellsX*dist[0]*xx,cell.getBottom()+cellsY*dist[1]*yy);
}
else
item.setPosition(pos[0]+cWidth*dist[0]*xx,pos[1]+cHeight*dist[1]*yy);
}
}
LL.save();
}
//check for safe cell sizes
if(Math.abs(cellsFloatX-cellsX)>0.00001||Math.abs(cellsFloatY-cellsY)>0.00001)
chooser([function(){},f]["No","Yes"],"The cells don't fill the screen as an exact vertical and/or horizontal number.\nDo you want to continue?","Warning");
else f();
}
function resetTags(){
var d=LL.getEvent().getContainer();
var i=LL.getEvent().getItem();
if(i!=null){ //Items Tag
//read tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+LL.getEvent().getContainer().getId()+"/items");
var all=JSON.parse(s).i;
var x;
var item;
for(x=0;x<all.length;x++){
item=all[x];
if(item.b==i.getId())break;
}
if(x==all.length){
text("Can't find Tags","Error 6");
return;
}
var tags=[];
for(property in item.an)
tags.push(property);
//If there are no Tags, do nothing
if(tags.length==0){
text("No Tags found","Error 7");
return;
}
//Option to delete all tags added to list
tags.unshift("All Tags");
var onClick = function(dialog,id){
//delete all selected Tags
alert(id+": "+tags[id]);
if(id==0)tags.shift();
else tags=[tags[id]];
for(var y=0;y<tags.length;y++)
i.setTag(tags[y].toString(),null);
Android.makeNewToast("Deleting tag(s) done!",true).show();
LL.save();
}
//ask user for selection
list(tags,onClick,"Which Tag do you want to reset?");
}
else{ //Container Tags
//read Tags from launcher file
var s=read(LL.getContext().getFilesDir().getPath()+"/pages/"+d.getId()+"/conf");
var data=JSON.parse(s);
var tags=[];
for(property in data.tags)
tags.push(property);
//Add the default tag to the List
if(data.tag!=null)tags.push("_");
//If there are no Tags, do nothing
if(tags.length==0){
text("No Tags found","Error 7");
return;
}
//Option to delete all tags added to list
tags.unshift("All Tags");
var onClick = function(dialog,id){
//delete all selected Tags
if(id==0)tags.shift();
else tags=[tags[id]];
for(var x=0;x<tags.length;x++){
if(tags[x]=="_")d.setTag(null);
else d.setTag(tags[x].toString(),null);
}
Android.makeNewToast("Deleting tag(s) done!",true).show();
LL.save();
}
//ask user for selection
list(tags,onClick,"Which Tag do you want to reset?");
}
}
function resetTool(){
var cont=LL.getEvent().getContainer();
var items=cont.getItems();
var listItems = ["Cell (only grid items) [0,0]","Position (only free items) [0,0]","Rotation (only free items) [0]","Scale (only free items) [1,1]","Skew (only free items) [0,0]","Size (only free items) [cell size]","Visibility [true]"];
var listener = new DialogInterface.OnMultiChoiceClickListener(){
onClick:function(dialog,which,isChecked){
bools[which]=isChecked;
}
};
var bools=[false,false,false,false,false,false,false];
var builder = new AlertDialog.Builder(LL.getContext());
builder.setMultiChoiceItems(listItems,bools,listener);
builder.setTitle("Reset");
builder.setCancelable(true);
builder.setPositiveButton("Confirm",new DialogInterface.OnClickListener(){
onClick:function(dialog,which){
dialog.dismiss();
for(var i=0;i<items.getLength();++i){
var t=items.getAt(i);
if(bools[0])t.setCell(0,0,1,1);
if(bools[1])t.setPosition(0,0);
if(bools[2])t.setRotation(0);
if(bools[3])t.setScale(1,1);
if(bools[4])t.setSkew(0,0);
if(bools[5])t.setSize(cont.getCellWidth(),cont.getCellHeight());
if(bools[6])t.setVisibility(true);
}
}
});
builder.show();
}
function saveLayout(){
LL.save();
Android.makeNewToast("Saved Layout",true).show();
}
function resetRecents(){
new File(LL.getContext().getFilesDir().getPath()+"/statistics").delete();
Android.makeNewToast("Recents resetted",true).show();
}
//function to display a grouped list where the user can select one item
//items should be an array containing arrays which first item is the group and the second item is an array of the items in this group
//onClickFunction has to have two arguments. first is group position, second is child position
function expandableList(items,onClickFunction,title){
var builder=new AlertDialog.Builder(LL.getContext());
var view=new ExpandableListView(LL.getContext());
//transform array of items into the correct format
var groupData=new ArrayList();
var childData=new ArrayList();
for(var x=0;x<items.length;x++)
{
var gd=new HashMap();
gd.put("root",items[x][0]);
var cd=new ArrayList();
groupData.add(gd);
for(var y=0;y<items[x][1].length;y++)
{
var cdMap=new HashMap();
cdMap.put("child",items[x][1][y]);
cd.add(cdMap);
}
childData.add(cd);
}
var mContext = LL.getContext().createPackageContext("com.faendir.lightning_launcher.multitool",0);
var layoutId = mContext.getResources().getIdentifier("list_item","layout","com.faendir.lightning_launcher.multitool");
//assign the items to an adapter
var adapter=new SimpleExpandableListAdapter(mContext,groupData,layoutId,["root"],[R.id.text1],childData,layoutId,["child"],[R.id.text1]);
//set function to run on Click to listener
var listener=new ExpandableListView.OnChildClickListener()
{
onChildClick:function(parent,view,groupPosition,childPosition,id)
{
dialog.dismiss();
setTimeout(function(){onClickFunction(groupPosition,childPosition);},0);
return true;
}
}
//assign adapter and listener to listview
view.setAdapter(adapter);
view.setOnChildClickListener(listener);
//finish building
builder.setView(view);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.cancel();}});
dialog=builder.create();
dialog.show();
}
//function to display a List in a Popup, where the user can select one item
function list(items,onClickFunction,title){
var builder=new AlertDialog.Builder(LL.getContext());
var listener=new DialogInterface.OnClickListener()
{
onClick:function(dialog,which)
{
dialog.dismiss();
setTimeout(function(){onClickFunction(dialog,which);},0);
return true;
}
}
builder.setItems(items,listener);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.cancel();}});//it has a Cancel Button
builder.show();
}
//function to display an alert like Dialog, but scrollable and with custom Title
function text(txt,title){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setMessage(txt);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNeutralButton("Close",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();}});
builder.show();
}
function chooser(functions,texts,txt,title){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setMessage(txt);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNeutralButton(texts[0],new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.dismiss();
setTimeout(functions[0],0);
}
});
if(functions.length>1)builder.setNegativeButton(texts[1],new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.dismiss();
setTimeout(functions[1],0);
}
});
if(functions.length>2)builder.setPositiveButton(texts[2],new DialogInterface.OnClickListener(){
onClick:function(dialog,id){
dialog.dismiss();
setTimeout(functions[2],0);
}
});
builder.show();
}
function customDialog(view,title){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setView(view);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNeutralButton("Close",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();}});
builder.show();
}
function customConfirmDialog(view,title,onPositiveFunction){
var builder=new AlertDialog.Builder(LL.getContext());
builder.setView(view);
builder.setCancelable(true);
builder.setTitle(title);
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();}});
builder.setPositiveButton("Confirm",new DialogInterface.OnClickListener(){onClick:function(dialog,id){dialog.dismiss();setTimeout(onPositiveFunction,0);}});
builder.show();
}
//helper function for item related, compute the center of an item
function center(item){
var r=item.getRotation()*Math.PI/180;
var sin=Math.abs(Math.sin(r));
var cos=Math.abs(Math.cos(r));
var w=item.getWidth()*item.getScaleX();
var h=item.getHeight()*item.getScaleY();
return[item.getPositionX()+(w*cos+h*sin)*0.5,item.getPositionY()+(h*cos+w*sin)*0.5];
}
//helper function for sorting labels
function noCaseSort(a,b){
if(a.toLowerCase()>b.toLowerCase())return 1;
if(a.toLowerCase()<b.toLowerCase())return -1;
return 0;
}
function read(filePath){
var file=new File(filePath);
var r=new BufferedReader(new FileReader(file));
var s="";
var l;
while((l=r.readLine())!=null)s+=(l+"\n");
return s;
}
function addImageIfNotNull(root,image,txt){
if(image!=null)
{
var textView=new TextView(LL.getContext());
textView.setText(txt+" ("+image.getWidth()+"x"+image.getHeight()+")");
root.addView(textView);
var imageView=new ImageView(LL.getContext());
imageView.setImageBitmap(image.getBitmap());
root.addView(imageView);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment