User Tools

Site Tools


script_shape_background

====== About the script ====== * Purpose : Set rectangles, circles, ovals, etc. as icons and backgrounds * Author : TBog * Link: www.google.com/+BogdanTautuTBog ====== How to use the script ====== Still in development, but the main feature will be that everything will be customizable with an internal GUI - Set the script in the category "Lightning menu" and "Item menu" then long-press on any container (panel was tested) or shortcut and run the script. - A dialog will appear that will guide you further. - Remember to scroll (if the preview image is too big) for the buttons Known issue: can't import an exported string ====== Script code ====== <sxh javascript> // v1.1.test6 function DrawData() { this.shapeArr = []; this.width = -1; this.height = -1; } var enumShapeType = { RECTANGLE: 1, OVAL: 2, ARC: 3, ROUND_RECT: 4, properties: { 1: {name: 'Rectangle'}, 2: {name: 'Oval'}, 3: {name: 'Arc'}, 4: {name: 'Round rectangle'}, }, findByName: function( name ) { for ( var key in enumShapeType.properties ) { if ( enumShapeType.properties[key].name == name ) return parseInt(key); } return enumShapeType.RECTANGLE; // should never happen }, getNameArr: function() { return [ enumShapeType.properties[enumShapeType.RECTANGLE].name, enumShapeType.properties[enumShapeType.ROUND_RECT].name, enumShapeType.properties[enumShapeType.OVAL].name, enumShapeType.properties[enumShapeType.ARC].name ]; }, getIdx: function( shapeType ) { var arr = this.getNameArr(); for ( var i = 0; i < arr.length; i+= 1 ) if ( shapeType == this.findByName(arr[i]) ) return i; return 0; // should never happen } }; function ShapeInfo() { this.name = "shape"; this.type = enumShapeType.OVAL; this.color = 0x80ff0000; this.width = -1; this.height = -1; this.offsetX = 0; this.offsetY = 0; this.fill = true; // for arc this.startAngle = 270; this.sweepAngle = 45; // for round corners this.cornerX = 10; this.cornerY = 20; this.validate = function( c ) { // if not all properties found, copy them to "c" for( var prop in this ) { if ( (typeof this[prop] == 'boolean') || (typeof this[prop] == 'number') || (typeof this[prop] == 'string') ) { if ( (typeof c[prop] == 'undefined') || (typeof c[prop] == 'object') ) c[prop] = this[prop]; } } if ( c.width < 0 ) c.width = this.width; if ( c.height < 0 ) c.height = this.height; }; } 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 drawShapes( canvas, shapeArr ) { bindClass( 'android.graphics.Paint' ); var w = canvas.getWidth(); var h = canvas.getHeight(); for ( var i = 0; i < shapeArr.length; i+= 1 ) { var shapeInfo = shapeArr[i]; var paint = new Paint( Paint.ANTI_ALIAS_FLAG ); paint.setColor( shapeInfo.color ); if ( shapeInfo.fill ) paint.setStyle( Paint.Style.FILL_AND_STROKE ); else paint.setStyle( Paint.Style.STROKE ); var shapeWidth = (shapeInfo.width >= 0) ? shapeInfo.width : w; var shapeHeight = (shapeInfo.height >= 0) ? shapeInfo.height : h; switch( parseInt(shapeInfo.type) ) { case enumShapeType.RECTANGLE: canvas.drawRect( shapeInfo.offsetX, shapeInfo.offsetY, shapeInfo.offsetX + shapeWidth, shapeInfo.offsetY + shapeHeight, paint ); break; case enumShapeType.OVAL: canvas.drawOval( shapeInfo.offsetX, shapeInfo.offsetY, shapeInfo.offsetX + shapeWidth, shapeInfo.offsetY + shapeHeight, paint ); break; case enumShapeType.ARC: canvas.drawArc( shapeInfo.offsetX, shapeInfo.offsetY, shapeInfo.offsetX + shapeWidth, shapeInfo.offsetY + shapeHeight, shapeInfo.startAngle, shapeInfo.sweepAngle, true, paint ); break; case enumShapeType.ROUND_RECT: canvas.drawRoundRect( shapeInfo.offsetX, shapeInfo.offsetY, shapeInfo.offsetX + shapeWidth, shapeInfo.offsetY + shapeHeight, shapeInfo.cornerX, shapeInfo.cornerY, paint ); break; default: Android.makeNewToast( 'Unknown shape type "' + shapeInfo.type + '"', true ).show(); } } } var g_cache = {itemId: null, data: null}; function getDrawData( item ) { if ( g_cache.itemId === item.getId() ) return g_cache.data; var jsonData = item.getTag('tbImgData'); if ( empty( jsonData ) ) { g_cache.data = new DrawData(); } else { var data = JSON.parse( jsonData ); if ( empty( data ) ) { g_cache.data = new DrawData(); } else { g_cache.data = data; } } g_cache.itemId = item.getId(); // hack to initialize with item size if ( g_cache.data.width <= 0 ) g_cache.data.width = item.getWidth(); if ( g_cache.data.height <= 0 ) g_cache.data.height = item.getHeight(); // validate shapes var defaultShape = new ShapeInfo(); defaultShape.width = g_cache.data.width; defaultShape.height = g_cache.data.height; for ( var i = 0; i < g_cache.data.shapeArr.length; i+= 1 ) { defaultShape.validate( g_cache.data.shapeArr[i] ); } return g_cache.data; } function setDrawData( item, data ) { if ( empty(data) ) item.setTag( 'tbImgData', null ); else item.setTag( 'tbImgData', JSON.stringify(data) ); g_cache.itemId = item.getId(); g_cache.data = data; } function showEditShape( item, shapeIdx ) { bindClass( 'android.app.AlertDialog' ); bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceListView' ); bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceText' ); bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceList' ); bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceColor' ); bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceSlider' ); bindClass( 'net.pierrox.lightning_launcher.prefs.LLPreferenceCheckBox' ); var drawData = getDrawData( item ); var shapeInfo = drawData.shapeArr[shapeIdx]; 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 prefName = new LLPreferenceText( 0, 'Name', shapeInfo.name, 'shape' ); var prefType = new LLPreferenceList( 0, 'Shape', enumShapeType.getNameArr(), enumShapeType.getIdx(shapeInfo.type), enumShapeType.OVAL ); var prefColor = new LLPreferenceColor( 0, 'Color', null, shapeInfo.color, 0xFFff0000, true ); var prefWidth = new LLPreferenceSlider(0, 'Width', 'pixel or -1', shapeInfo.width, -1, 'INT', 0, 512, 1, 'px'); var prefHeight = new LLPreferenceSlider(0, 'Height', 'pixel or -1', shapeInfo.height, -1, 'INT', 0, 512, 1, 'px'); var prefOffX = new LLPreferenceSlider(0, 'Offset X', 'pixel', shapeInfo.offsetX, 0, 'INT', 0, 512, 1, 'px'); var prefOffY = new LLPreferenceSlider(0, 'Offset Y', 'pixel', shapeInfo.offsetY, 0, 'INT', 0, 512, 1, 'px'); var prefCornerRadX = new LLPreferenceSlider(0, 'Corner radius X', 'pixel', shapeInfo.cornerX, 0, 'INT', 0, 512, 1, 'px'); var prefCornerRadY = new LLPreferenceSlider(0, 'Corner radius Y', 'pixel', shapeInfo.cornerY, 0, 'INT', 0, 512, 1, 'px'); var prefStartAng = new LLPreferenceSlider(0, 'Start angle', 'degree', shapeInfo.startAngle, 0, 'INT', 0, 360, 1, 'deg'); var prefSweepAng = new LLPreferenceSlider(0, 'Sweep angle', 'degree', shapeInfo.sweepAngle, 0, 'INT', 0, 360, 1, 'deg'); var prefFill = new LLPreferenceCheckBox( 0, 'Fill', null, shapeInfo.fill, null ); var prefList = new LLPreferenceListView( ctxTheme, null ); prefList.setCompactMode(true); var prefListener = { onLLPreferenceChanged: function( pref ) { if ( pref == prefType ) { var type = enumShapeType.findByName( prefType.getLabels()[prefType.getValueIndex()] ); switch ( type ) { case enumShapeType.RECTANGLE: case enumShapeType.OVAL: prefStartAng.setVisible(false); prefSweepAng.setVisible(false); prefCornerRadX.setVisible(false); prefCornerRadY.setVisible(false); break; case enumShapeType.ARC: prefStartAng.setVisible(true); prefSweepAng.setVisible(true); prefCornerRadX.setVisible(false); prefCornerRadY.setVisible(false); break; case enumShapeType.ROUND_RECT: prefStartAng.setVisible(false); prefSweepAng.setVisible(false); prefCornerRadX.setVisible(true); prefCornerRadY.setVisible(true); break; } prefList.refresh(); } }, onLLPreferenceClicked: function( pref ) { }, onLLPreferenceLongClicked: function( pref ) { } }; prefList.setListener( prefListener ); prefList.setPreferences( [ prefName, prefType, prefColor, prefWidth, prefHeight, prefOffX, prefOffY, prefCornerRadX, prefCornerRadY, prefStartAng, prefSweepAng, prefFill ] ); prefListener.onLLPreferenceChanged( prefType ); builder.setView( prefList ); builder.setTitle( 'Edit shape #' + shapeIdx ); var dialog; builder.setCancelable( false ); builder.setNeutralButton( 'Close', { onClick: function( dialog, id ) { dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showShapeMenu(item);}, 0); } } ); builder.setPositiveButton( 'Save', { onClick: function( dialog, id ) { var drawData = getDrawData( item ); var shapeInfo = drawData.shapeArr[shapeIdx]; shapeInfo.name = prefName.getValue(); shapeInfo.type = enumShapeType.findByName( prefType.getLabels()[prefType.getValueIndex()] ); shapeInfo.color = prefColor.getColor(); shapeInfo.width = prefWidth.getValue(); shapeInfo.height = prefHeight.getValue(); shapeInfo.offsetX = prefOffX.getValue(); shapeInfo.offsetY = prefOffY.getValue(); shapeInfo.fill = prefFill.isChecked(); shapeInfo.startAngle = prefStartAng.getValue(); shapeInfo.sweepAngle = prefSweepAng.getValue(); shapeInfo.cornerX = prefCornerRadX.getValue(); shapeInfo.cornerY = prefCornerRadY.getValue(); setDrawData( item, drawData ); dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showShapeMenu(item);}, 0); } } ); dialog = builder.create(); dialog.show(); } function showShapeMenu( item ) { bindClass( 'android.app.AlertDialog' ); bindClass( 'android.content.DialogInterface' ); bindClass( 'android.text.Html' ); bindClass( 'android.text.InputType' ); bindClass( 'android.view.View' ); bindClass( 'android.view.ViewGroup' ); bindClass( 'android.view.ViewGroup.LayoutParams' ); bindClass( 'android.view.ContextThemeWrapper' ); bindClass( 'android.widget.ListView' ); bindClass( 'android.widget.LinearLayout' ); bindClass( 'android.widget.LinearLayout.LayoutParams' ); bindClass( 'android.widget.ScrollView' ); bindClass( 'android.widget.TextView' ); bindClass( 'android.widget.EditText' ); bindClass( 'android.widget.ImageView' ); bindClass( 'android.widget.Button' ); bindClass( 'android.graphics.Bitmap' ); bindClass( 'android.graphics.Canvas' ); bindClass( 'android.graphics.drawable.BitmapDrawable' ); bindClass( 'android.R' ); var drawData = getDrawData( item ); 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 ); rootView.addView( linearView ); builder.setView( rootView ); builder.setTitle( 'Shape list' ); var dialog; linearView.setOrientation( LinearLayout.VERTICAL ); var shapeInfoLayout, shapeName, shapeRemove, shapeEdit; for ( var i = 0; i < drawData.shapeArr.length; i+= 1 ) { var shapeInfo = drawData.shapeArr[i]; if ( empty(shapeInfo) ) { drawData.shapeArr.splice(i--, 1); continue; } linearView.addView( shapeInfoLayout = new LinearLayout( ctxTheme ) ); shapeInfoLayout.addView( shapeName = new TextView( ctxTheme ), new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0) ); shapeName.setText( Html.fromHtml('<b>' + i + '</b>. ' + shapeInfo.name) ); shapeInfoLayout.addView( shapeEdit = new ImageView( ctxTheme ) ); shapeEdit.setImageResource( R.drawable.ic_menu_edit ); shapeEdit.setTag(i); shapeEdit.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var idx = parseInt( view.getTag() ); var drawData = getDrawData( item ); if ( idx >= drawData.shapeArr.length ) { Android.makeNewToast( 'Failed to edit shape #' + idx, true ).show(); } Android.makeNewToast( 'Edit shape #' + idx, true ).show(); dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showEditShape(item, idx);}, 0); } } ); shapeInfoLayout.addView( shapeRemove = new ImageView( ctxTheme ) ); shapeRemove.setImageResource( R.drawable.ic_menu_delete ); shapeRemove.setTag(i); shapeRemove.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var idx = parseInt( view.getTag() ); var drawData = getDrawData( item ); if ( idx >= drawData.shapeArr.length ) { Android.makeNewToast( 'Failed to remove shape #' + idx, true ).show(); } delete drawData.shapeArr[idx]; Android.makeNewToast( 'Removed shape #' + idx, true ).show(); setDrawData(item, drawData); dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showShapeMenu(item);}, 0); } } ); } var shapeAdd; linearView.addView( shapeInfoLayout = new LinearLayout( ctxTheme ) ); shapeInfoLayout.addView( shapeAdd = new ImageView( ctxTheme ) ); shapeAdd.setImageResource( R.drawable.ic_menu_add ); shapeAdd.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); drawData.shapeArr.push( new ShapeInfo() ); Android.makeNewToast( 'New shape', true ).show(); setDrawData(item, drawData); dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showShapeMenu(item);}, 0); } } ); linearView.addView( shapeName = new TextView( ctxTheme ) ); shapeName.setText( 'Preview' ); var bitmap = Bitmap.createBitmap(drawData.width, drawData.height, Bitmap.Config.ARGB_8888); var c = new Canvas( bitmap ); drawShapes( c, drawData.shapeArr ); var shapeCanvas; linearView.addView( shapeCanvas = new ImageView( ctxTheme ) ); shapeCanvas.setImageDrawable( new BitmapDrawable(ctx.getResources(), bitmap) ); var hex = Number(item.getId()).toString(16); hex = "000000".substr(0, 6 - hex.length) + hex; linearView.addView( shapeName = new TextView( ctxTheme ) ); shapeName.setText( Html.fromHtml('Current selected item is <b>#' + hex + '</b>. ') ); var editWidth, editHeight; linearView.addView( shapeInfoLayout = new LinearLayout( ctxTheme ) ); shapeInfoLayout.addView( shapeName = new TextView( ctxTheme ) ); shapeName.setText( 'Width' ); shapeInfoLayout.addView( editWidth = new EditText( ctxTheme ) ); editWidth.setText( '' + drawData.width ); editWidth.setInputType( InputType.TYPE_CLASS_NUMBER ); linearView.addView( shapeInfoLayout = new LinearLayout( ctxTheme ) ); shapeInfoLayout.addView( shapeName = new TextView( ctxTheme ) ); shapeName.setText( 'Height' ); shapeInfoLayout.addView( editHeight = new EditText( ctxTheme ) ); editHeight.setText( '' + drawData.height ); editHeight.setInputType( InputType.TYPE_CLASS_NUMBER ); linearView.addView( shapeInfoLayout = new LinearLayout( ctxTheme ) ); var btn; shapeInfoLayout.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Set size' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); drawData.width = parseInt( editWidth.getText() ); drawData.height = parseInt( editHeight.getText() ); setDrawData( item, drawData ); dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showShapeMenu(item);}, 0); } }); shapeInfoLayout.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Reset size' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); drawData.width = item.getWidth(); drawData.height = item.getHeight(); setDrawData( item, drawData ); dialog.dismiss(); var time = setTimeout(function(){clearTimeout(time); showShapeMenu(item);}, 0); } }); linearView.addView( shapeName = new TextView( ctxTheme ) ); shapeName.setText( 'Actions' ); if ( item.getType() == 'Shortcut' ) { linearView.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Set custom icon' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); var img = LL.createImage( drawData.width, drawData.height ); item.setCustomIcon( img ); drawShapes( img.draw(), drawData.shapeArr ); img.update(); } }); linearView.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Set image (temporary)' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var img = LL.createImage( { draw: function(context) { var canvas = context.getCanvas(); var item = context.getItem(); // Currently this method will only return a value when drawing shortcut icons (set through setImage(Image)), otherwise it will return null. drawShapes( canvas, getDrawData( item ).shapeArr ); } }, -1, -1); item.setImage( img ); } }); linearView.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Set icon background layer' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); var img = LL.createImage( drawData.width, drawData.height ); item.setIconLayer( img, 'b', false ); drawShapes( img.draw(), drawData.shapeArr ); img.update(); item.setIconLayer( img, 'b', true ); } }); } linearView.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Set box background' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); var img = LL.createImage( drawData.width, drawData.height ); item.setBoxBackground( img, 'nsf', false ); drawShapes( img.draw(), drawData.shapeArr ); img.update(); item.setBoxBackground( img, 'nsf', true ); } }); linearView.addView( btn = new Button( ctxTheme ) ); btn.setAllCaps( false ); btn.setText( 'Export to string' ); btn.setOnClickListener( new View.OnClickListener() { onClick: function( view ) { var drawData = getDrawData( item ); var text = JSON.stringify(drawData); var ctx = getActiveScreen().getContext(); //bindClass( 'android.content.Context' ); bindClass( 'android.content.ClipboardManager' ); bindClass( 'android.content.ClipData' ); var clipboard = ctx.getSystemService(Context.CLIPBOARD_SERVICE); var clip = ClipData.newPlainText('shape export', text); clipboard.setPrimaryClip(clip); Android.makeNewToast('Shape data exported to clipboard.', true).show(); } }); builder.setCancelable( true ); builder.setNeutralButton( 'Close', { onClick: function( dialog, id ) { dialog.dismiss(); } } ); dialog = builder.create(); dialog.setOnShowListener( new DialogInterface.OnShowListener() { onShow:function() { rootView.scrollTo(0,0); } } ); dialog.show(); } var event = getEvent(); switch ( event.getSource() ) { case 'MENU_ITEM': case 'I_CLICK': case 'SHORTCUT': showShapeMenu( event.getItem() ); return; case 'MENU_APP': showShapeMenu( event.getContainer().getOpener() ); return; default: alert( 'unknown event source ' + event.getSource() ); return; } </sxh>

script_shape_background.txt · Last modified: 2017/06/20 18:26 by tbog