Lower indention on pressing backspace

Signed-off-by: Stefan Niedermann <info@niedermann.it>
This commit is contained in:
Stefan Niedermann 2021-07-22 14:55:06 +02:00 committed by Niedermann IT-Dienstleistungen
parent 14a3e6928c
commit f24dae9e96
3 changed files with 166 additions and 0 deletions

View file

@ -5,6 +5,7 @@ import android.os.Build;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.EditText;
import androidx.annotation.ColorInt;
@ -35,6 +36,7 @@ import it.niedermann.android.markdown.markwon.handler.StrikethroughEditHandler;
import it.niedermann.android.markdown.markwon.plugins.SearchHighlightPlugin;
import it.niedermann.android.markdown.markwon.plugins.ThemePlugin;
import it.niedermann.android.markdown.markwon.textwatcher.CombinedTextWatcher;
import it.niedermann.android.markdown.markwon.textwatcher.LowerIndentionKeyListener;
import it.niedermann.android.markdown.markwon.textwatcher.SearchHighlightTextWatcher;
public class MarkwonMarkdownEditor extends AppCompatEditText implements MarkdownEditor {
@ -62,6 +64,7 @@ public class MarkwonMarkdownEditor extends AppCompatEditText implements Markdown
combinedWatcher = new CombinedTextWatcher(editor, this);
addTextChangedListener(combinedWatcher);
setOnKeyListener(new LowerIndentionKeyListener(this));
setCustomSelectionActionModeCallback(new ContextBasedRangeFormattingCallback(this));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setCustomInsertionActionModeCallback(new ContextBasedFormattingCallback(this));

View file

@ -0,0 +1,64 @@
package it.niedermann.android.markdown.markwon.textwatcher;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.View;
import androidx.annotation.NonNull;
import it.niedermann.android.markdown.markwon.MarkwonMarkdownEditor;
import it.niedermann.android.markdown.model.EListType;
import static it.niedermann.android.markdown.MarkdownUtil.getEndOfLine;
import static it.niedermann.android.markdown.MarkdownUtil.getStartOfLine;
public class LowerIndentionKeyListener implements View.OnKeyListener {
private final MarkwonMarkdownEditor editor;
public LowerIndentionKeyListener(@NonNull MarkwonMarkdownEditor editor) {
this.editor = editor;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
if (editor.getSelectionStart() == editor.getSelectionEnd()) {
final int cursor = editor.getSelectionStart();
final Editable text = editor.getEditableText();
final int lineStart = getStartOfLine(text, cursor);
final int lineEnd = getEndOfLine(text, cursor);
if (cursor != lineEnd) {
return false;
}
final String line = text.subSequence(lineStart, lineEnd).toString();
final String trimmedLine = line.trim();
for (EListType listType : EListType.values()) {
if (listType.listSymbol.equals(trimmedLine)) {
if (line.trim().length() == EListType.DASH.listSymbol.length()) {
return lowerIndention(line, lineStart, text);
}
} else if (listType.checkboxUnchecked.equals(trimmedLine) || listType.checkboxChecked.equals(trimmedLine)) {
if (line.trim().length() == EListType.DASH.checkboxUnchecked.length()) {
return lowerIndention(line, lineStart, text);
}
}
}
}
}
return false;
}
private boolean lowerIndention(String line, int lineStart, @NonNull Editable text) {
if (line.startsWith(" ")) {
text.replace(lineStart, lineStart + 2, "");
editor.setMarkdownStringModel(text);
return true;
} else if (line.startsWith(" ")) {
text.replace(lineStart, lineStart + 1, "");
editor.setMarkdownStringModel(text);
return true;
}
return false;
}
}

View file

@ -0,0 +1,99 @@
package it.niedermann.android.markdown.markwon.textwatcher;
import android.view.KeyEvent;
import android.widget.EditText;
import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
import androidx.test.core.app.ApplicationProvider;
import junit.framework.TestCase;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import it.niedermann.android.markdown.markwon.MarkwonMarkdownEditor;
import it.niedermann.android.markdown.model.EListType;
@RunWith(RobolectricTestRunner.class)
public class LowerIndentionKeyListenerTest extends TestCase {
@Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
private EditText editText;
@Before
public void reset() {
this.editText = new MarkwonMarkdownEditor(ApplicationProvider.getApplicationContext());
}
@Test
public void shouldLowerIndentionByTwoWhenPressingBackspaceOnAnIndentedList() {
this.editText.setText(" - ");
pressBackspace(4);
assertText("- ", 2);
this.editText.setText("- [ ] Foo\n - [ ] ");
pressBackspace(18);
assertText("- [ ] Foo\n- [ ] ", 16);
}
@Test
public void shouldLowerIndentionByOneWhenPressingBackspaceOnAListWhichIsIndentedByOneSpace() {
this.editText.setText(" - ");
pressBackspace(3);
assertText("- ", 2);
}
@Test
public void shouldNotLowerIndentionByOneWhenCursorIsNotAtTheEnd() {
this.editText.setText(" - ");
pressBackspace(2);
assertText(" ", 1);
this.editText.setText(" - ");
pressBackspace(0);
assertText(" - ", 0);
this.editText.setText(" - ");
pressBackspace(3);
assertText(" ", 2);
this.editText.setText(" - ");
pressBackspace(2);
assertText(" - ", 1);
this.editText.setText("- Foo\n - ");
pressBackspace(9);
assertText("- Foo\n ", 8);
}
@Test
public void shouldDeleteLastCharacterWhenPressingBackspace() {
this.editText.setText("");
pressBackspace(0);
assertText("", 0);
this.editText.setText("- Foo");
pressBackspace(5);
assertText("- Fo", 4);
this.editText.setText("- [ ] Foo");
pressBackspace(9);
assertText("- [ ] Fo", 8);
}
private void pressBackspace(int atPosition) {
this.editText.setSelection(atPosition);
this.editText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL, 0));
}
private void assertText(String expected, int cursorPosition) {
assertEquals(expected, this.editText.getText().toString());
assertEquals(cursorPosition, this.editText.getSelectionStart());
assertEquals(cursorPosition, this.editText.getSelectionEnd());
}
}