From 4bd3f7635dc053986945216dd188c7e3b4c1b1c5 Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Mon, 18 Mar 2019 20:41:59 +0100 Subject: [PATCH 01/24] Automatic indentation on newline. When you enter a newline, spaces are inserted automatically based on the indent of the previous line and the last character. This is not a final change, more of a proof of concept regarding the script editor. More to come! (hopefully) --- .../activities/ScriptEditor.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index df827fc..c200844 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -344,6 +344,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic mScriptText = (AdvancedEditText) findViewById(R.id.sc_text); mScriptText.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL)); mScriptText.addTextChangedListener(mScriptTextWatcher); + mScriptText.addTextChangedListener(mScriptTextWatcherIndent); mScriptText.setListener(new AdvancedEditText.OnAdvancedEditTextEvent() { private float mInitialTextSize; @Override @@ -1240,4 +1241,72 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic b.setOnLongClickListener(mCompletionButtonLongClickListener); mCompletionsViewGroup.addView(b); } + + + // ------------- autoindentation ------------ + + String mSpanNewline = "mSpanNewline"; + public static final int INDENT_SIZE = 2; + + TextWatcher mScriptTextWatcherIndent = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if(count == 1 && s.charAt(start) == '\n'){ + mScriptText.getText().setSpan(mSpanNewline,start,start,0); + } + } + + @Override + public void afterTextChanged(Editable editable) { + int posEnter = editable.getSpanStart(mSpanNewline); + editable.removeSpan(mSpanNewline); + if (posEnter == -1 || editable.charAt(posEnter) != '\n') return; + + int pos = posEnter; + + //get previous char + char prev = pos == 0 ? '\0' : editable.charAt(pos-1); + + //goto previous line + do { + pos--; + } while(pos >= 0 && editable.charAt(pos) != '\n'); + + + //find indent size + int n = 0; + boolean cont = true; + while(cont){ + pos++; + switch (editable.charAt(pos)){ + case ' ': + n++; + break; + case '\t': + n+=INDENT_SIZE; + break; + default: + cont = false; + } + } + //add indent size + switch (prev){ + case '{': + n+=INDENT_SIZE; + break; + case '}': + n-=INDENT_SIZE; + break; + } + + //write indent + for(int i=0;i Date: Sat, 23 Mar 2019 13:18:21 +0100 Subject: [PATCH 02/24] Added shortcut buttons. Currently two types: text and keys. --- .../activities/ScriptEditor.java | 87 +++++++++++++++++++ .../app/src/main/res/layout/script_editor.xml | 34 ++++++-- 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index c200844..082b208 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -302,6 +302,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic // mCompletionsListView = (ListView) findViewById(R.id.completions); mCompletionsViewGroup = (ViewGroup) findViewById(R.id.completions); + initializeShortcuts((ViewGroup) findViewById(R.id.shortcuts)); + Button btn; btn = (Button)findViewById(R.id.sc_import); @@ -1309,4 +1311,89 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } } }; + + + // -------------- shortcuts -------------------- + + private interface Shortcut { + String getLabel(); + void apply(AdvancedEditText editText); + } + + private static class ShortcutKey implements Shortcut { + int key; + String label; + + ShortcutKey(String label, int key) { + this.key = key; + this.label = label; + } + + @Override + public String getLabel() { + return label; + } + + @Override + public void apply(AdvancedEditText editText) { + editText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, + key, 0)); + editText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_UP, + key, 0)); + } + } + + private static class ShortcutText implements Shortcut { + String preText; + String postText; + + ShortcutText(String preText, String postText) { + this.preText = preText; + this.postText = postText; + } + + @Override + public String getLabel() { + return preText + "·" + postText; + } + + @Override + public void apply(AdvancedEditText editText) { + int start = editText.getSelectionStart(); + int end = editText.getSelectionEnd(); + editText.getEditableText().replace(start, end, preText+postText); + editText.setSelection(start + preText.length()); + } + } + + private static Shortcut[] mShortcuts = new Shortcut[]{ + new ShortcutKey("←",KeyEvent.KEYCODE_DPAD_LEFT), + new ShortcutKey("↑",KeyEvent.KEYCODE_DPAD_UP), + new ShortcutKey("↓",KeyEvent.KEYCODE_DPAD_DOWN), + new ShortcutKey("→",KeyEvent.KEYCODE_DPAD_RIGHT), + new ShortcutText("(", ")"), + new ShortcutText("[", "]"), + new ShortcutText("{", "}"), + }; + + private View.OnClickListener mShortcutButtonClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + Button btn = (Button) v; + Shortcut shortcut = (Shortcut) btn.getTag(); + shortcut.apply(mScriptText); + //mInputMethodManager.restartInput(mScriptText); + } + }; + + private void initializeShortcuts(ViewGroup view) { + LayoutInflater inflater = getLayoutInflater(); + for (Shortcut shortcut : mShortcuts) { + Button b = (Button) inflater.inflate(R.layout.sc_btn, null); + b.setTag(shortcut); + b.setText(shortcut.getLabel()); + b.setOnClickListener(mShortcutButtonClickListener); + view.addView(b); + } + } } diff --git a/app/llx/app/src/main/res/layout/script_editor.xml b/app/llx/app/src/main/res/layout/script_editor.xml index e45be68..522858b 100644 --- a/app/llx/app/src/main/res/layout/script_editor.xml +++ b/app/llx/app/src/main/res/layout/script_editor.xml @@ -26,17 +26,37 @@ - + android:layout_gravity="bottom|left" + android:orientation="vertical"> - - + android:layout_height="wrap_content" + android:layout_gravity="bottom|left"> + + + + + + + + + + Date: Sat, 23 Mar 2019 18:11:30 +0100 Subject: [PATCH 03/24] Remove deprecated class 'array' from autocompletion Some other import changes (by android studio) --- .../lightning_launcher/activities/ScriptEditor.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 082b208..9111f66 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -49,9 +49,8 @@ import net.pierrox.lightning_launcher.Version; import net.pierrox.lightning_launcher.data.FileUtils; import net.pierrox.lightning_launcher.data.Utils; import net.pierrox.lightning_launcher.engine.LightningEngine; -import net.pierrox.lightning_launcher.script.ScriptManager; import net.pierrox.lightning_launcher.script.Script; -import net.pierrox.lightning_launcher.script.api.Array; +import net.pierrox.lightning_launcher.script.ScriptManager; import net.pierrox.lightning_launcher.script.api.Box; import net.pierrox.lightning_launcher.script.api.Container; import net.pierrox.lightning_launcher.script.api.Desktop; @@ -71,7 +70,6 @@ import net.pierrox.lightning_launcher.script.api.Panel; import net.pierrox.lightning_launcher.script.api.PropertyEditor; import net.pierrox.lightning_launcher.script.api.PropertySet; import net.pierrox.lightning_launcher.script.api.RectL; -import net.pierrox.lightning_launcher.script.api.Shortcut; import net.pierrox.lightning_launcher.script.api.StopPoint; import net.pierrox.lightning_launcher.util.FileAndDirectoryPickerDialog; import net.pierrox.lightning_launcher.util.FileProvider; @@ -956,7 +954,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic private void buildAutoCompleteTokens() { sAutoCompleteTokens = new ArrayList<>(); Class[] classes = { - Array.class, + //Array.class, Box.class, net.pierrox.lightning_launcher.script.api.Binding.class, Container.class, @@ -981,7 +979,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic PropertySet.class, RectL.class, net.pierrox.lightning_launcher.script.api.Script.class, - Shortcut.class, + net.pierrox.lightning_launcher.script.api.Shortcut.class, net.pierrox.lightning_launcher.script.api.Lightning.class, net.pierrox.lightning_launcher.script.api.Menu.class, ComponentName.class, From 66564f381b921ec187657ca92bd3b2adf5cf769e Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Sat, 23 Mar 2019 18:13:27 +0100 Subject: [PATCH 04/24] shortcut buttons are placed outside the editor --- .../activities/ScriptEditor.java | 1 + .../app/src/main/res/layout/script_editor.xml | 44 +++++++++---------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 9111f66..8588345 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -1372,6 +1372,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic new ShortcutText("(", ")"), new ShortcutText("[", "]"), new ShortcutText("{", "}"), + new ShortcutText("var ", ""), }; private View.OnClickListener mShortcutButtonClickListener = new View.OnClickListener() { diff --git a/app/llx/app/src/main/res/layout/script_editor.xml b/app/llx/app/src/main/res/layout/script_editor.xml index 522858b..46acccd 100644 --- a/app/llx/app/src/main/res/layout/script_editor.xml +++ b/app/llx/app/src/main/res/layout/script_editor.xml @@ -13,41 +13,39 @@ android:id="@+id/sc_h" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" + android:layout_gravity="center_horizontal" android:text="@string/sc_h" - android:textStyle="italic" - android:layout_gravity="center_horizontal" /> + android:textAppearance="?android:attr/textAppearanceSmall" + android:textStyle="italic" /> - + android:layout_weight="1"> - + - - - - - - + android:layout_gravity="bottom|left"> + + + + + android:layout_gravity="bottom|center_horizontal"> Date: Fri, 29 Mar 2019 00:40:32 +0100 Subject: [PATCH 05/24] Improved autoindentation with brackets --- .../activities/ScriptEditor.java | 141 ++++++++++++------ 1 file changed, 99 insertions(+), 42 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 8588345..7976964 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -1246,6 +1246,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic // ------------- autoindentation ------------ String mSpanNewline = "mSpanNewline"; + String mSpanEndBracket = "mSpanEndBracket"; public static final int INDENT_SIZE = 2; TextWatcher mScriptTextWatcherIndent = new TextWatcher() { @@ -1258,58 +1259,114 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic if(count == 1 && s.charAt(start) == '\n'){ mScriptText.getText().setSpan(mSpanNewline,start,start,0); } + if(count == 1 && s.charAt(start) == '}'){ + mScriptText.getText().setSpan(mSpanEndBracket, start, start, 0); + } } @Override public void afterTextChanged(Editable editable) { - int posEnter = editable.getSpanStart(mSpanNewline); + int spanPos; + + spanPos = editable.getSpanStart(mSpanNewline); editable.removeSpan(mSpanNewline); - if (posEnter == -1 || editable.charAt(posEnter) != '\n') return; + if (spanPos != -1 && editable.charAt(spanPos) == '\n') + onNewLine(spanPos, editable); - int pos = posEnter; + spanPos = editable.getSpanStart(mSpanEndBracket); + editable.removeSpan(mSpanEndBracket); + if (spanPos != -1 && editable.charAt(spanPos) == '}') + onEndBracket(spanPos, editable); - //get previous char - char prev = pos == 0 ? '\0' : editable.charAt(pos-1); - - //goto previous line - do { - pos--; - } while(pos >= 0 && editable.charAt(pos) != '\n'); - - - //find indent size - int n = 0; - boolean cont = true; - while(cont){ - pos++; - switch (editable.charAt(pos)){ - case ' ': - n++; - break; - case '\t': - n+=INDENT_SIZE; - break; - default: - cont = false; - } - } - //add indent size - switch (prev){ - case '{': - n+=INDENT_SIZE; - break; - case '}': - n-=INDENT_SIZE; - break; - } - - //write indent - for(int i=0;i= 0 && editable.charAt(currentpos) != '\n'); + } + currentpos++; + + //find indent size + int n = 0; + boolean cont = true; + while(cont && currentpos < editable.length()){ + switch (editable.charAt(currentpos)){ + case ' ': + n++; + break; + case '\t': + n+=INDENT_SIZE; + break; + //case '\n': + default: + cont = false; + } + currentpos++; + } + return n; + } + + private void onNewLine(int posEnter, Editable editable){ + + int n = getIndentLength(posEnter, editable); + StringBuilder indent = new StringBuilder(); + for(int i=0;i 0 && editable.charAt(posEnter - 1) == '{'){ + + //add newline if also following close bracket + if(posEnter < editable.length() - 1 && editable.charAt(posEnter + 1) == '}'){ + editable.insert(posEnter + 1, "\n" + indent.toString()); //warning! this mustn't trigger the 'onNewline' again + mScriptText.setSelection(posEnter + 1); + } + + //add indent size + for(int i=0;i= INDENT_SIZE && (posBracket - n == 0 || editable.charAt(posBracket - n - 1) == '\n')){ + + //remove the first tab, or all the spaces if no tabs found + int p = 1; + while(p <= INDENT_SIZE){ + if(editable.charAt(posBracket - p) == '\t'){ + //tab found, remove + editable.replace(posBracket - p, posBracket - p + 1, ""); + break; + } + p++; + } + if(p == INDENT_SIZE + 1){ + //no tabs found, only spaces, remove them + editable.replace(posBracket - INDENT_SIZE, posBracket, ""); + } + } + } + // -------------- shortcuts -------------------- From aa6547fbbd0f0e6f9fbbc02d6e1fbbd0be7d1ad2 Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Sun, 31 Mar 2019 20:49:43 +0200 Subject: [PATCH 06/24] Avoid infinite 'onTextChanged' events --- .../lightning_launcher/activities/ScriptEditor.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 7976964..1d93cb7 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -1247,6 +1247,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic String mSpanNewline = "mSpanNewline"; String mSpanEndBracket = "mSpanEndBracket"; + boolean mEditing = false; public static final int INDENT_SIZE = 2; TextWatcher mScriptTextWatcherIndent = new TextWatcher() { @@ -1256,6 +1257,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic @Override public void onTextChanged(CharSequence s, int start, int before, int count) { + if(mEditing) return; + if(count == 1 && s.charAt(start) == '\n'){ mScriptText.getText().setSpan(mSpanNewline,start,start,0); } @@ -1266,6 +1269,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic @Override public void afterTextChanged(Editable editable) { + mEditing = true; int spanPos; spanPos = editable.getSpanStart(mSpanNewline); @@ -1278,6 +1282,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic if (spanPos != -1 && editable.charAt(spanPos) == '}') onEndBracket(spanPos, editable); + mEditing = false; } }; @@ -1329,7 +1334,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic //add newline if also following close bracket if(posEnter < editable.length() - 1 && editable.charAt(posEnter + 1) == '}'){ - editable.insert(posEnter + 1, "\n" + indent.toString()); //warning! this mustn't trigger the 'onNewline' again + editable.insert(posEnter + 1, "\n" + indent.toString()); mScriptText.setSelection(posEnter + 1); } From 105c935cca32e0065bec5ddd6fefd273410a847b Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Sun, 31 Mar 2019 21:13:36 +0200 Subject: [PATCH 07/24] fix for incorrect check when tabs present --- .../activities/ScriptEditor.java | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 1d93cb7..9cef2c8 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -24,6 +24,7 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.text.Editable; import android.text.TextWatcher; +import android.util.Pair; import android.util.SparseArray; import android.view.GestureDetector; import android.view.KeyEvent; @@ -1287,13 +1288,13 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic }; /** - * Returns the size of the indent in the current line (spaces at the left) + * Returns the size of the indent in the current line (spaces at the left) and the position of the first non-space char * @param currentpos pos of current line (any char) * @param editable where to search - * @return + * @return length of indent (number of spaces) and position of first non-space char (can be end of file) */ - private int getIndentLength(int currentpos, Editable editable){ - //goto beginning of line + private Pair getLineIndent(int currentpos, Editable editable){ + // goto beginning of line if(currentpos != 0) { do{ currentpos--; @@ -1301,73 +1302,78 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } currentpos++; - //find indent size + // find indent size int n = 0; boolean cont = true; while(cont && currentpos < editable.length()){ switch (editable.charAt(currentpos)){ case ' ': n++; + currentpos++; break; case '\t': n+=INDENT_SIZE; + currentpos++; break; //case '\n': default: cont = false; } - currentpos++; } - return n; + return new Pair<>(n, currentpos); } private void onNewLine(int posEnter, Editable editable){ - int n = getIndentLength(posEnter, editable); + int n = getLineIndent(posEnter, editable).first; StringBuilder indent = new StringBuilder(); for(int i=0;i 0 && editable.charAt(posEnter - 1) == '{'){ - //add newline if also following close bracket + // add newline if also following close bracket if(posEnter < editable.length() - 1 && editable.charAt(posEnter + 1) == '}'){ editable.insert(posEnter + 1, "\n" + indent.toString()); mScriptText.setSelection(posEnter + 1); } - //add indent size + // add indent size for(int i=0;i= INDENT_SIZE && (posBracket - n == 0 || editable.charAt(posBracket - n - 1) == '\n')){ + + Pair n_beg = getLineIndent(posBracket, editable); + int n = n_beg.first; + int beg = n_beg.second; + + // check if beginning of line and indent to remove + if( n >= INDENT_SIZE && posBracket == beg ){ - //remove the first tab, or all the spaces if no tabs found + // remove the first tab, or all the spaces if no tabs found int p = 1; while(p <= INDENT_SIZE){ if(editable.charAt(posBracket - p) == '\t'){ //tab found, remove - editable.replace(posBracket - p, posBracket - p + 1, ""); + editable.delete(posBracket - p, posBracket - p + 1); break; } p++; } if(p == INDENT_SIZE + 1){ - //no tabs found, only spaces, remove them - editable.replace(posBracket - INDENT_SIZE, posBracket, ""); + // no tabs found, only spaces, remove them + editable.delete(posBracket - INDENT_SIZE, posBracket); } } } From 9a7b7fbde2603fc2109d339abdc4d43263c0edc6 Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Mon, 1 Apr 2019 22:58:39 +0200 Subject: [PATCH 08/24] Action buttons: increase/decrease indent --- .../activities/ScriptEditor.java | 88 ++++++++++++------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 9cef2c8..cea7c35 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -1299,8 +1299,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic do{ currentpos--; }while (currentpos >= 0 && editable.charAt(currentpos) != '\n'); - } - currentpos++; + currentpos++; + } // find indent size int n = 0; @@ -1352,32 +1352,52 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic private void onEndBracket(int posBracket, Editable editable){ - // check if first of line - - Pair n_beg = getLineIndent(posBracket, editable); - int n = n_beg.first; - int beg = n_beg.second; - - // check if beginning of line and indent to remove - if( n >= INDENT_SIZE && posBracket == beg ){ - - // remove the first tab, or all the spaces if no tabs found - int p = 1; - while(p <= INDENT_SIZE){ - if(editable.charAt(posBracket - p) == '\t'){ - //tab found, remove - editable.delete(posBracket - p, posBracket - p + 1); - break; - } - p++; - } - if(p == INDENT_SIZE + 1){ - // no tabs found, only spaces, remove them - editable.delete(posBracket - INDENT_SIZE, posBracket); - } + // check if beginning of line + if( posBracket == getLineIndent(posBracket, editable).second ){ + // decrease indent + decreaseIndent( posBracket, editable ); } } + private void increaseIndent(int posCursor, Editable editable){ + + Pair n_beg = getLineIndent(posCursor, editable); + int beg = n_beg.second; + + if(posCursor < beg){ + // cursor before the start of line, just move there + mScriptText.setSelection(beg); + } else { + // increase indent adding spaces + for(int i=0; i< INDENT_SIZE; i++) editable.insert(beg, " "); + } + } + + private void decreaseIndent(int posCursor, Editable editable){ + + Pair n_beg = getLineIndent(posCursor, editable); + int n = n_beg.first; + int beg = n_beg.second; + + if(posCursor < beg){ + // cursor before the start of line, just move there + mScriptText.setSelection(beg); + } else if ( n >= INDENT_SIZE ){ + // enough intent to remove, remove the first tab, or all the spaces if no tabs found + int p = 1; + while (p <= INDENT_SIZE) { + if (editable.charAt(beg - p) == '\t') { + //tab found, remove + editable.delete(beg - p, beg - p + 1); + return; + } + p++; + } + // no tabs found, only spaces, remove them + editable.delete(beg - INDENT_SIZE, beg); + } + } + // -------------- shortcuts -------------------- @@ -1387,8 +1407,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } private static class ShortcutKey implements Shortcut { - int key; - String label; + private int key; + private String label; ShortcutKey(String label, int key) { this.key = key; @@ -1410,8 +1430,8 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } private static class ShortcutText implements Shortcut { - String preText; - String postText; + private String preText; + private String postText; ShortcutText(String preText, String postText) { this.preText = preText; @@ -1437,10 +1457,12 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic new ShortcutKey("↑",KeyEvent.KEYCODE_DPAD_UP), new ShortcutKey("↓",KeyEvent.KEYCODE_DPAD_DOWN), new ShortcutKey("→",KeyEvent.KEYCODE_DPAD_RIGHT), - new ShortcutText("(", ")"), - new ShortcutText("[", "]"), - new ShortcutText("{", "}"), - new ShortcutText("var ", ""), + new ShortcutAction(0), + new ShortcutAction(1), + new ShortcutText("(", ")"), + new ShortcutText("[", "]"), + new ShortcutText("{", "}"), + new ShortcutText("var ", ""), }; private View.OnClickListener mShortcutButtonClickListener = new View.OnClickListener() { From 45a3b1680ce4876883cbae50aa9032ec835cc9ff Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Wed, 3 Apr 2019 16:38:46 +0200 Subject: [PATCH 09/24] Added missing action buttons from previous commit. When using the 'modify indent' buttons, all the lines selected are modified. --- .../activities/ScriptEditor.java | 90 ++++++++++++++++--- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index cea7c35..029101e 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -23,6 +23,7 @@ import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.Editable; +import android.text.Spanned; import android.text.TextWatcher; import android.util.Pair; import android.util.SparseArray; @@ -81,7 +82,9 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.List; import fr.xgouchet.texteditor.ui.AdvancedEditText; @@ -1359,18 +1362,42 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } } + private Pair modifyIndent(int posLeft, int posRight, boolean increase, Editable editable){ + String span = "modifyIntent"; + editable.setSpan(span, posLeft, posRight, Spanned.SPAN_EXCLUSIVE_INCLUSIVE); + + Deque positions = new ArrayDeque<>(); + while(posLeft <= posRight && posLeft < editable.length()){ + // mark position to indent + positions.push(posLeft); + posLeft++; + + // find next line + while(posLeft <= posRight && posLeft < editable.length() && editable.charAt(posLeft) != '\n') + posLeft++; + posLeft++; + } + + for (Integer position : positions) { + // indent the lines in reverse order + if(increase) + increaseIndent(position, editable); + else + decreaseIndent(position, editable); + } + + //restore span + return new Pair<>(editable.getSpanStart(span), editable.getSpanEnd(span)); + } + private void increaseIndent(int posCursor, Editable editable){ Pair n_beg = getLineIndent(posCursor, editable); int beg = n_beg.second; - if(posCursor < beg){ - // cursor before the start of line, just move there - mScriptText.setSelection(beg); - } else { - // increase indent adding spaces - for(int i=0; i< INDENT_SIZE; i++) editable.insert(beg, " "); - } + // increase indent adding spaces + for(int i=0; i< INDENT_SIZE; i++) editable.insert(beg, " "); + } private void decreaseIndent(int posCursor, Editable editable){ @@ -1379,10 +1406,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic int n = n_beg.first; int beg = n_beg.second; - if(posCursor < beg){ - // cursor before the start of line, just move there - mScriptText.setSelection(beg); - } else if ( n >= INDENT_SIZE ){ + if ( n >= INDENT_SIZE ){ // enough intent to remove, remove the first tab, or all the spaces if no tabs found int p = 1; while (p <= INDENT_SIZE) { @@ -1451,14 +1475,52 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic editText.setSelection(start + preText.length()); } } + enum SA { + DEC_TAB, + INC_TAB, + } + private class ShortcutAction implements Shortcut { + private SA action; + + ShortcutAction(SA action) { + this.action = action; + } + + @Override + public String getLabel() { + switch (action) { + case DEC_TAB: + return "⇤"; + case INC_TAB: + return "⇥"; + } + return "?"; + } + + @Override + public void apply(AdvancedEditText editText) { + switch (action) { + case DEC_TAB: + Pair selectionI = + modifyIndent(editText.getSelectionStart(), editText.getSelectionEnd(), false, editText.getEditableText()); + editText.setSelection(selectionI.first, selectionI.second); + break; + case INC_TAB: + Pair selectionD = + modifyIndent(editText.getSelectionStart(), editText.getSelectionEnd(), true, editText.getEditableText()); + editText.setSelection(selectionD.first, selectionD.second); + break; + } + } + } - private static Shortcut[] mShortcuts = new Shortcut[]{ + private Shortcut[] mShortcuts = new Shortcut[]{ new ShortcutKey("←",KeyEvent.KEYCODE_DPAD_LEFT), new ShortcutKey("↑",KeyEvent.KEYCODE_DPAD_UP), new ShortcutKey("↓",KeyEvent.KEYCODE_DPAD_DOWN), new ShortcutKey("→",KeyEvent.KEYCODE_DPAD_RIGHT), - new ShortcutAction(0), - new ShortcutAction(1), + new ShortcutAction(SA.DEC_TAB), + new ShortcutAction(SA.INC_TAB), new ShortcutText("(", ")"), new ShortcutText("[", "]"), new ShortcutText("{", "}"), From d11f5aff26fd7c8da23d53992125f0089fe830f4 Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Wed, 3 Apr 2019 17:29:58 +0200 Subject: [PATCH 10/24] Added comments (removed use of external variable inside indentation function, to help moving the functionality to a new class) --- .../activities/ScriptEditor.java | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index 029101e..a8d2790 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -1264,9 +1264,11 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic if(mEditing) return; if(count == 1 && s.charAt(start) == '\n'){ + // newline inserted mScriptText.getText().setSpan(mSpanNewline,start,start,0); } if(count == 1 && s.charAt(start) == '}'){ + // end bracket inserted mScriptText.getText().setSpan(mSpanEndBracket, start, start, 0); } } @@ -1276,11 +1278,13 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic mEditing = true; int spanPos; + // check newline spanPos = editable.getSpanStart(mSpanNewline); editable.removeSpan(mSpanNewline); if (spanPos != -1 && editable.charAt(spanPos) == '\n') onNewLine(spanPos, editable); + // check endbracket spanPos = editable.getSpanStart(mSpanEndBracket); editable.removeSpan(mSpanEndBracket); if (spanPos != -1 && editable.charAt(spanPos) == '}') @@ -1326,6 +1330,11 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic return new Pair<>(n, currentpos); } + /** + * Called when a newline is inserted. Indents it with the same indentation as the previous line (if any) + * @param posEnter position of the newline char + * @param editable where to indent + */ private void onNewLine(int posEnter, Editable editable){ int n = getLineIndent(posEnter, editable).first; @@ -1339,8 +1348,9 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic // add newline if also following close bracket if(posEnter < editable.length() - 1 && editable.charAt(posEnter + 1) == '}'){ - editable.insert(posEnter + 1, "\n" + indent.toString()); - mScriptText.setSelection(posEnter + 1); + editable.insert(posEnter + 2, "\n" + indent.toString() + "}"); + // this avoids moving the cursor + editable.replace(posEnter + 1, posEnter + 2, ""); } // add indent size @@ -1353,6 +1363,11 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic editable.insert(posEnter + 1, indent.toString()); } + /** + * Called when an ending bracket is inserted. Decreases the indentation. + * @param posBracket where the endbracket was + * @param editable where to unindent + */ private void onEndBracket(int posBracket, Editable editable){ // check if beginning of line @@ -1362,6 +1377,14 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } } + /** + * Changes the indentation of all the lines selected + * @param posLeft start of selection + * @param posRight end of selection + * @param increase if trur increase indent, descrease otherwise + * @param editable where to apply the indentation + * @return the new selection (may have changed due to the indentation changes) + */ private Pair modifyIndent(int posLeft, int posRight, boolean increase, Editable editable){ String span = "modifyIntent"; editable.setSpan(span, posLeft, posRight, Spanned.SPAN_EXCLUSIVE_INCLUSIVE); @@ -1390,6 +1413,11 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic return new Pair<>(editable.getSpanStart(span), editable.getSpanEnd(span)); } + /** + * Increases the indentation of a single line + * @param posCursor position of a character in the line that will be indented + * @param editable where to apply the indentation + */ private void increaseIndent(int posCursor, Editable editable){ Pair n_beg = getLineIndent(posCursor, editable); @@ -1399,7 +1427,12 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic for(int i=0; i< INDENT_SIZE; i++) editable.insert(beg, " "); } - + + /** + * Decreases the indentation of a single line + * @param posCursor position of a character in the line that will be indented + * @param editable where to apply the indentation + */ private void decreaseIndent(int posCursor, Editable editable){ Pair n_beg = getLineIndent(posCursor, editable); @@ -1425,11 +1458,24 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic // -------------- shortcuts -------------------- + /** + * Represents a button in the bottom of the editor. + */ private interface Shortcut { + /** + * Label to display + */ String getLabel(); + + /** + * Runned when the button is pressed + */ void apply(AdvancedEditText editText); } + /** + * This button will send a key to the editText. + */ private static class ShortcutKey implements Shortcut { private int key; private String label; @@ -1453,6 +1499,9 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } } + /** + * This button will insert a text before and after the cursor. + */ private static class ShortcutText implements Shortcut { private String preText; private String postText; @@ -1475,10 +1524,14 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic editText.setSelection(start + preText.length()); } } + enum SA { DEC_TAB, INC_TAB, } + /** + * This button will trigger an action + */ private class ShortcutAction implements Shortcut { private SA action; @@ -1514,6 +1567,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic } } + // list of shortcuts to display private Shortcut[] mShortcuts = new Shortcut[]{ new ShortcutKey("←",KeyEvent.KEYCODE_DPAD_LEFT), new ShortcutKey("↑",KeyEvent.KEYCODE_DPAD_UP), From bc1176eeebadfeaa09162a3c391ade36a6f4f36c Mon Sep 17 00:00:00 2001 From: TrianguloY Date: Wed, 3 Apr 2019 17:47:34 +0200 Subject: [PATCH 11/24] Moved Indentation functions to new Class for better modularization --- .../activities/ScriptEditor.java | 223 +---------------- .../lightning_launcher/util/Indentation.java | 229 ++++++++++++++++++ 2 files changed, 236 insertions(+), 216 deletions(-) create mode 100644 app/llx/app/src/main/java/net/pierrox/lightning_launcher/util/Indentation.java diff --git a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java index a8d2790..a3370cc 100644 --- a/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java +++ b/app/llx/app/src/main/java/net/pierrox/lightning_launcher/activities/ScriptEditor.java @@ -23,7 +23,6 @@ import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.Editable; -import android.text.Spanned; import android.text.TextWatcher; import android.util.Pair; import android.util.SparseArray; @@ -75,6 +74,7 @@ import net.pierrox.lightning_launcher.script.api.RectL; import net.pierrox.lightning_launcher.script.api.StopPoint; import net.pierrox.lightning_launcher.util.FileAndDirectoryPickerDialog; import net.pierrox.lightning_launcher.util.FileProvider; +import net.pierrox.lightning_launcher.util.Indentation; import net.pierrox.lightning_launcher_extreme.BuildConfig; import net.pierrox.lightning_launcher_extreme.R; @@ -82,9 +82,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Deque; import java.util.List; import fr.xgouchet.texteditor.ui.AdvancedEditText; @@ -125,6 +123,7 @@ public class ScriptEditor extends ResourceWrapperActivity implements View.OnClic private CheckBox mMenuCustom; private ArrayAdapter