====== Differences ====== This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
script_multitool [2015/04/23 17:24] lm13 |
script_multitool [2016/02/09 08:08] (current) st1d |
||
---|---|---|---|
Line 2: | Line 2: | ||
* Purpose : This script is a multifunctional tool to do or show a lot of stuff | * Purpose : This script is a multifunctional tool to do or show a lot of stuff | ||
* Author : [[https://plus.google.com/+LukasMorawietz|LM13]] | * Author : [[https://plus.google.com/+LukasMorawietz|LM13]] | ||
- | * Current Version : 2.6 | ||
* Link : https://plus.google.com/115366157037831519359/posts/fQwfu5AUj5m | * Link : https://plus.google.com/115366157037831519359/posts/fQwfu5AUj5m | ||
* Download available! (Check repository) | * Download available! (Check repository) | ||
- | |||
- | ====== Changelog ====== | ||
- | * Version 1.0 (20/7/2014): initial release in wiki | ||
- | * Version 1.1 (21/7/2014): replaced move item script with trianguloY's solution. | ||
- | * Version 1.2 (25/7/2014): replaced change home page with move pages to extend functionality, sorted choices on script-side | ||
- | * Version 1.2.1 (26/7/2014): added Intent to Item details | ||
- | * Version 1.3 (28/7/2014): fix: no touch data in swipe event, add resize, add save, add containers ID | ||
- | * Version 1.3.1 (31/8/2014): fix: Intent also for folders | ||
- | * Version 2.0 (14/9/2014): new UI, added comments, removed the easteregg, because it's not reachable through the new UI | ||
- | * Version 2.1 (24/9/2014): UI updated again, now selection is sorted into categorys, added import, export and autoformat scripts | ||
- | * Version 2.2 (4/10/2014): Abilility to View and Reset all tags, not only the default one. | ||
- | * Version 2.3 (5/11/2014): Added Icon and Background image view, added progress to autoformat to show the user what gets done | ||
- | * Version 2.4 (16/1/2015): Added search a string in all scripts, improved script import/export and improved some graphics. Improved code readability | ||
- | * Version 2.5 (24/2/2015): Removed Play store page (native feature now), fixed script import, added reset app history | ||
- | * Version 2.6 (23/4/2015): Fixed Autoformat & reset tag, added compatibility for trial version | ||
====== How to use the script ====== | ====== How to use the script ====== | ||
- | * enable the script in any menu or event you want to run it | + | * see App |
====== Current functionality ====== | ====== Current functionality ====== | ||
Line 45: | Line 29: | ||
//please report all bugs in the g+ community// | //please report all bugs in the g+ community// | ||
- | <spoiler|Script> | + | <spoiler|Script (won't work without the apk)> |
<sxh javascript;>//Created by Lukas Morawietz in collaboration with TrianguloY | <sxh javascript;>//Created by Lukas Morawietz in collaboration with TrianguloY | ||
Line 336: | Line 320: | ||
} | } | ||
//check for valid input | //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])))){ | + | if(!done||move==null||move[0]==null||(move[0]!="*"&&isNaN(parseInt(move[0])))||move[1]==null||(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 exportScripts(){ | + | |
- | //Directory to save scripts in | + | |
- | var dir=new File(Environment.getExternalStorageDirectory()+File.separator+"LightningLauncher"+File.separator+"Scripts"+File.separator); | + | |
- | dir.mkdirs();//create Directory if missing | + | |
- | //Iterate through all scripts | + | |
- | var scripts=LL.getAllScriptMatching(Script.FLAG_ALL); | + | |
- | for(var a=0;a<scripts.length;a++) | + | |
- | { | + | |
- | var s=scripts.getAt(a); | + | |
- | var file=new File(dir.getAbsolutePath()+File.separator+s.getId()+"_"+convertToFile(s.getName())+".js");//Define the file to save in | + | |
- | file.createNewFile();//create the file | + | |
- | //Check for Flags | + | |
- | var app=s.hasFlag(Script.FLAG_APP_MENU); | + | |
- | var item=s.hasFlag(Script.FLAG_ITEM_MENU); | + | |
- | var custom=s.hasFlag(Script.FLAG_CUSTOM_MENU); | + | |
- | var flags="//Flags"; | + | |
- | if(app)flags+=" app"; | + | |
- | if(item)flags+=" item"; | + | |
- | if(custom)flags+=" custom"; | + | |
- | flags+=" Name: "+s.getName()+"\n"; | + | |
- | //write the code to the file | + | |
- | var f=new FileWriter(file); | + | |
- | f.write(flags+s.getText()); | + | |
- | f.flush(); | + | |
- | f.close(); | + | |
- | } | + | |
- | Android.makeNewToast("Scripts saved to "+dir.getAbsolutePath(),true).show(); | + | |
- | } | + | |
- | + | ||
- | function import_askForInput(){ | + | |
- | //ask android to let the user select a textfile | + | |
- | var i=new Intent(Intent.ACTION_GET_CONTENT); | + | |
- | i.setType("*/*"); | + | |
- | i.addCategory(Intent.CATEGORY_OPENABLE); | + | |
- | LL.startActivityForResult(Intent.createChooser(i,"Select Script to import"),LL.getCurrentScript(),null); | + | |
- | } | + | |
- | + | ||
- | function import_handleInput(){ | + | |
- | //the file to import | + | |
- | var file=new File(data.getData().getPath()); | + | |
- | //check for valid file | + | |
- | if(!file.canRead()){ | + | |
- | text("Can't read file","Error 3"); | + | |
- | return; | + | |
- | } | + | |
- | if(file.length()>100000){ | + | |
- | text("File is too big","Error 4"); | + | |
- | return; | + | |
- | } | + | |
- | + | ||
- | var s = read(file.getAbsolutePath()); | + | |
- | var endOfFirstLine = s.indexOf("\n"); | + | |
- | if(endOfFirstLine == -1) endOfFirstLine = s.length; | + | |
- | var l = s.substring(0,endOfFirstLine); | + | |
- | if(l.indexOf("//Flags")!=-1){ //check if file contains flag settings | + | |
- | var app=(l.indexOf("app")!=-1); | + | |
- | var item=(l.indexOf("item")!=-1); | + | |
- | var custom=(l.indexOf("custom")!=-1); | + | |
- | s = s.substring(endOfFirstLine + 1); | + | |
- | } | + | |
- | var filename=""; | + | |
- | if(l.indexOf("Name: ")!=-1)filename = l.substring(l.indexOf("Name: ")+6).trim(); | + | |
- | if(filename==""){ | + | |
- | //remove file extension | + | |
- | var filename=file.getName(); | + | |
- | var index=filename.lastIndexOf("."); | + | |
- | if(index!=-1)filename=filename.slice(0,index); | + | |
- | } | + | |
- | //ask for imported scripts name | + | |
- | var name=prompt("File read successfully. Enter name for the Script",filename); | + | |
- | if(name == null || name.trim() == "") return; | + | |
- | //Write read data to script and create it if necessary | + | |
- | var script=LL.getScriptByName(name); | + | |
- | var f=function(){ | + | |
- | script.setText(s); | + | |
- | //apply flags if found before | + | |
- | if(app)script.setFlag(Script.FLAG_APP_MENU,true); | + | |
- | if(item)script.setFlag(Script.FLAG_ITEM_MENU,true); | + | |
- | if(custom)script.setFlag(Script.FLAG_CUSTOM_MENU,true); | + | |
- | Android.makeNewToast("Script import done!",true); | + | |
- | } | + | |
- | if(script!=null){ | + | |
- | chooser([function(){},f],["No","Yes"],"Script does already exist. Overwrite?","Warning"); | + | |
- | } | + | |
- | else { | + | |
- | script=LL.createScript(name,s,0); | + | |
- | f(); | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | function autoFormat(){ | + | |
- | //create Strings to display | + | |
- | var title="Which script?"; | + | |
- | var items=[]; | + | |
- | var scripts=LL.getAllScriptMatching(Script.FLAG_ALL); | + | |
- | for(var z=0;z<scripts.length;z++)items.push(scripts.getAt(z).getName()); | + | |
- | items.sort(noCaseSort); | + | |
- | items.unshift("All Scripts (may need some time)"); | + | |
- | + | ||
- | //initialize vars | + | |
- | canceled=false; | + | |
- | + | ||
- | //handle user selection | + | |
- | var onClick = function(dialog,id){ | + | |
- | if(id==0) selected=items.slice(1,items.length);//all scripts selected | + | |
- | else selected=[items[id]];//single script selected | + | |
- | y=0;//indicates currently handled script | + | |
- | setTimeout(formatNextScript,0);//initializes the format of the next script | + | |
- | } | + | |
- | + | ||
- | //show selection list | + | |
- | list(items,onClick,title); | + | |
- | } | + | |
- | + | ||
- | function searchScripts(){ | + | |
- | var search=prompt("String to search (regexp)\n/____/gim",""); | + | |
- | if(search==null)return; | + | |
- | eval("search=/"+search+"/gim");//RegExp is not defined? õ_o | + | |
- | var scripts=LL.getAllScriptMatching(Script.FLAG_ALL); | + | |
- | var output="Matches (lines):\n"; | + | |
- | + | ||
- | for(var t=0;t<scripts.getLength();++t){ | + | |
- | var script=scripts.getAt(t); | + | |
- | var founds=script.getText().split(search); | + | |
- | if(founds.length==1)continue; | + | |
- | output+=script.getName()+": "; | + | |
- | var line=1; | + | |
- | for(var s=0;s<founds.length-1;++s){ | + | |
- | var lb=founds[s].match(/\n/g); | + | |
- | line+=lb==null?0:lb.length; | + | |
- | output+=(s==0?"":", ")+line; | + | |
- | } | + | |
- | output+="\n"; | + | |
- | //strange, but functional, way to find the line of the matches | + | |
- | } | + | |
- | text(output,"Matches"); | + | |
- | } | + | |
- | + | ||
- | 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); | + | |
- | } | + | |
- | } | + | |
- | }); | + | |
- | } | + | |
- | + | ||
- | 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); | + | |
- | } | + | |
- | //assign the items to an adapter | + | |
- | var adapter=new SimpleExpandableListAdapter(LL.getContext(),groupData,R.layout.simple_expandable_list_item_1,["root"],[R.id.text1],childData,R.layout.simple_expandable_list_item_1,["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); | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | function convertToFile(n){ | + | |
- | return n.replace(/[,./\:*?""<>|]/g,"_"); | + | |
- | } | + | |
- | + | ||
- | function formatNextScript(){ | + | |
- | s=LL.getScriptByName(selected[y]); | + | |
- | t=s.getText();//original text | + | |
- | //create a dialog to indicate how far the script is handled already | + | |
- | progress=new ProgressDialog(LL.getContext()); | + | |
- | progress.setMax(t.length); | + | |
- | progress.setMessage("Initializing..."); | + | |
- | progress.setTitle(selected[y]); | + | |
- | progress.setCancelable(false); | + | |
- | progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); | + | |
- | progress.setButton(AlertDialog.BUTTON_NEGATIVE,"Cancel",new DialogInterface.OnClickListener(){onClick:function(){canceled=true;}}); | + | |
- | progress.show(); | + | |
- | out="";//output | + | |
- | i=0;//indentionlevel | + | |
- | noCode=false;//detectionhelper,true if in comment,string etc. | + | |
- | starter="";//detectionhelper,contains the last noCode block starter | + | |
- | newLine=true;//true if in a new line | + | |
- | switchLevel=[];//detectionhelper,needed for switch commands | + | |
- | a=0; | + | |
- | progress.setMessage(t.split("\n",1)[0]);//set the first line to the dialog | + | |
- | //go through the text | + | |
- | setTimeout(processNextChar,0); | + | |
- | } | + | |
- | + | ||
- | function processNextChar(){ | + | |
- | if(canceled){ //if canceled by user stop | + | |
- | progress.cancel(); | + | |
- | return; | + | |
- | } | + | |
- | progress.setProgress(a+1);//increase char processed counter | + | |
- | //don't copy spaces and tabs, if not in a noCode block | + | |
- | if(noCode||((t[a]!=" "||(out[out.length-1].toLowerCase()!=out[out.length-1].toUpperCase()&&t[a+1].toLowerCase()!=t[a+1].toUpperCase())||out.slice(out.length-4,out.length)=="case"||out.slice(out.length-6,out.length)=="return")&&(t[a]!="\t"))){ | + | |
- | //detect whether the char is negated by a backslash or not | + | |
- | var backslashed=false; | + | |
- | for(b=out.length-1;out[b]=="\\";b--)backslashed=!backslashed; | + | |
- | + | ||
- | //detect start of a noCode block | + | |
- | if((t[a]=="\""||t[a]=="\'")&&!noCode){ | + | |
- | noCode=true; | + | |
- | starter=t[a]; | + | |
- | if(out[out.length-1]=="\n")indentLine(); | + | |
- | } | + | |
- | else if(!noCode&&t[a]=="/"&&(t[a+1]=="/"||t[a+1]=="*")){ | + | |
- | noCode=true; | + | |
- | starter=t.slice(a,a+2); | + | |
- | if(out[out.length-1]=="\n")indentLine(); | + | |
- | } | + | |
- | //detect end of a noCode block | + | |
- | else if(noCode&&(t[a]==starter||(starter=="/*"&&t.slice(a,a+2)=="*/")||(starter=="//"&&t[a]=="\n"))&&!backslashed) | + | |
- | noCode=false; | + | |
- | + | ||
- | //handle keychars | + | |
- | if(!noCode){ | + | |
- | if(t[a]=="\n"){ //line end | + | |
- | newLine=true; | + | |
- | //set the next line to the dialog | + | |
- | progress.setMessage(t.slice(a+1).split("\n",1)[0]); | + | |
- | } | + | |
- | else{ | + | |
- | if(t[a]=="}"){ //function block end | + | |
- | i--; | + | |
- | if(switchLevel.length!=0&&i<=switchLevel[0]&&switchLevel[0]>0){ //special handling when in switch command | + | |
- | switchLevel.shift(); | + | |
- | i--; | + | |
- | } | + | |
- | } | + | |
- | if(newLine&&t[a]!="\n")//indent the next line | + | |
- | indentLine(); | + | |
- | if(t[a]=="{")i++;//function block start | + | |
- | if(t.slice(a,a+7)=="switch(")switchLevel.unshift(++i);//start of switch command | + | |
- | } | + | |
- | } | + | |
- | out=out.concat(t[a]);//concat the char | + | |
- | } | + | |
- | a++; | + | |
- | if(a<t.length)setTimeout(processNextChar,0); | + | |
- | else{ | + | |
- | while(out[out.length-1]=="\n")out=out.slice(0,out.length-1);//remove unnecessary line brakes at the end of the script | + | |
- | s.setText(out);//set the text to the script | + | |
- | y++; | + | |
- | progress.dismiss(); | + | |
- | if(y<selected.length)setTimeout(format,0);//process next script if there is one | + | |
- | else Android.makeNewToast("Done!",true).show();//notify if finished | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | function indentLine(){ //creates tabs at the beginning of a line | + | |
- | for(b=(switchLevel!=0&&(t.slice(a,a+4)=="case"||t.slice(a,a+7)=="default")?1:0);b<i;b++) | + | |
- | out=out.concat("\t"); | + | |
- | newLine=false; | + | |
- | } | + | |
- | </sxh> | + | |
- | </spoiler> | + | |
- | + | ||
- | + | ||
- | ====== Included Scripts ====== | + | |
- | * [[script_autoformat|Autoformat other scripts]] | + | |
- | * [[script_export_scripts|Export Scripts]] | + |