Skip to content

Commit

Permalink
fixed line numbers view
Browse files Browse the repository at this point in the history
  • Loading branch information
guanglinn committed Sep 16, 2024
1 parent f9affdd commit c86bc4d
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 90 deletions.
24 changes: 11 additions & 13 deletions src/main/java/org/billthefarmer/editor/Editor.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,12 @@ public class Editor extends Activity
private String path;
private Uri content;
private String match;
private NewEditText textView;
private EditText textView;
private TextView customView;
private MenuItem searchItem;
private SearchView searchView;
private ScrollView scrollView;
private LineNumbersTextView lineNumbersView;
private Runnable updateHighlight;
private Runnable updateWordCount;

Expand Down Expand Up @@ -447,7 +448,7 @@ public class Editor extends Activity
private int type = MONO;

private int syntax;
private long lineNumbersRefreshTime = 0;
private long refreshTime = 0; // Line numbers refresh time on scroll changed

// onCreate
@Override
Expand Down Expand Up @@ -541,8 +542,6 @@ protected void onCreate(Bundle savedInstanceState)
if (savedInstanceState != null)
edit = savedInstanceState.getBoolean(EDIT);

textView.setLineNumbersEnabled(lineNumbers);

if (!edit)
{
textView.setRawInputType(InputType.TYPE_NULL);
Expand All @@ -556,6 +555,10 @@ else if (!suggest)

setSizeAndTypeface(size, type);

lineNumbersView = findViewById(R.id.lineNumbersView);
lineNumbersView.setEditText(textView);
lineNumbersView.setLineNumbersEnabled(lineNumbers);

Intent intent = getIntent();
Uri uri = intent.getData();

Expand Down Expand Up @@ -752,9 +755,9 @@ public void onTextChanged(CharSequence s,
{
if (lineNumbers) {
final long time = System.currentTimeMillis();
if (time - lineNumbersRefreshTime > 100) {
lineNumbersRefreshTime = time;
textView.invalidate(); // Update line numbers
if (time - refreshTime > 125) {
refreshTime = time;
lineNumbersView.setText(""); // To refresh line numbers
}
}

Expand Down Expand Up @@ -1345,8 +1348,6 @@ private void viewClicked(MenuItem item)
textView.setRawInputType(InputType.TYPE_NULL);
textView.setTextIsSelectable(true);
textView.clearFocus();
if (lineNumbers)
textView.setLineNumbersEnabled(true);

// Update boolean
edit = false;
Expand Down Expand Up @@ -1398,9 +1399,6 @@ private void newFile(String text)
if (text != null)
textView.append(text);

if (lineNumbers)
textView.setLineNumbersEnabled(true);

setTitle(uri.getLastPathSegment());
match = UTF_8;
getActionBar().setSubtitle(match);
Expand Down Expand Up @@ -1911,7 +1909,7 @@ private void lineNumbersClicked(MenuItem item)
{
lineNumbers = !lineNumbers;
item.setChecked(lineNumbers);
textView.setLineNumbersEnabled(lineNumbers);
lineNumbersView.setLineNumbersEnabled(lineNumbers);
}

// suggestClicked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,55 @@
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.TextView;

public class NewEditText extends EditText {
public class LineNumbersTextView extends TextView {
private boolean isLineNumbersEnabled;
private final LineNumbersDrawer lineNumbersDrawer = new LineNumbersDrawer(this);
private LineNumbersDrawer lineNumbersDrawer;

public NewEditText(Context context) {
public LineNumbersTextView(Context context) {
super(context);
}

public NewEditText(Context context, AttributeSet attrs) {
public LineNumbersTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public NewEditText(Context context, AttributeSet attrs, int defStyleAttr) {
public LineNumbersTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
public boolean onPreDraw() {
lineNumbersDrawer.setTextSize(getTextSize());
return super.onPreDraw();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if (isLineNumbersEnabled) {
lineNumbersDrawer.draw(canvas);
}
}

public void setEditText(final EditText editor) {
lineNumbersDrawer = new LineNumbersDrawer(editor, this);
}

public void setLineNumbersEnabled(final boolean enabled) {
if (enabled ^ isLineNumbersEnabled) {
post(this::invalidate);
}
isLineNumbersEnabled = enabled;
if (isLineNumbersEnabled) {
lineNumbersDrawer.startLineTracking();
lineNumbersDrawer.prepare();
} else {
lineNumbersDrawer.reset();
lineNumbersDrawer.stopLineTracking();
lineNumbersDrawer.stop();
}
}

/**
* Count instances of a single char in a char sequence.
*/
public static int countChar(final CharSequence s, int start, int end, final char c) {
int count = 0;
for (int i = start; i < end; i++) {
if (s.charAt(i) == c) {
count++;
}
}
return count;
}

static class LineNumbersDrawer {

private final EditText _editor;
public final EditText _editor;
public final LineNumbersTextView _textView;
private final Paint _paint = new Paint();

private final int _defaultPaddingLeft;
private static final int LINE_NUMBER_PADDING_LEFT = 6;
private static final int LINE_NUMBER_PADDING_LEFT = 1;
private static final int LINE_NUMBER_PADDING_RIGHT = 12;

private final Rect _visibleArea = new Rect();
Expand All @@ -89,13 +73,14 @@ static class LineNumbersDrawer {
private final TextWatcher _lineTrackingWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
_maxNumber -= countChar(s, start, start + count, '\n');
_maxNumber -= countChar(s, start, start + count, '\n');
_maxNumber -= countLines(s, start, start + count);
_textView.setText(" ");
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
_maxNumber += countChar(s, start, start + count, '\n');
_maxNumber += countLines(s, start, start + count);
_textView.setText(" ");
}

@Override
Expand All @@ -104,27 +89,35 @@ public void afterTextChanged(Editable editable) {
}
};

public LineNumbersDrawer(final EditText editor) {
public LineNumbersDrawer(final EditText editor, final LineNumbersTextView textView) {
_editor = editor;
_textView = textView;
_paint.setColor(0xFF999999);
_paint.setTextAlign(Paint.Align.RIGHT);
_defaultPaddingLeft = editor.getPaddingLeft();
}

public void setTextSize(final float textSize) {
_paint.setTextSize(textSize);
private int countLines(final CharSequence s, int start, int end) {
int count = 0;
for (int i = start; i < end; i++) {
if (s.charAt(i) == '\n') {
count++;
}
}
return count;
}

public boolean isTextSizeChanged() {
if (_paint.getTextSize() == _oldTextSize) {
private boolean isTextSizeChanged() {
final float textSize = _editor.getTextSize();
if (textSize == _oldTextSize) {
return false;
} else {
_oldTextSize = _paint.getTextSize();
_paint.setTextSize(textSize);
_oldTextSize = textSize;
return true;
}
}

public boolean isMaxNumberDigitsChanged() {
private boolean isMaxNumberDigitsChanged() {
final int oldDigits = _maxNumberDigits;

if (_maxNumber < 10) {
Expand All @@ -141,7 +134,7 @@ public boolean isMaxNumberDigitsChanged() {
return _maxNumberDigits != oldDigits;
}

public boolean isOutOfLineNumbersArea() {
private boolean isOutOfLineNumbersArea() {
final int margin = (int) (_visibleArea.height() * 0.5f);
final int top = _visibleArea.top - margin;
final int bottom = _visibleArea.bottom + margin;
Expand All @@ -157,20 +150,34 @@ public boolean isOutOfLineNumbersArea() {
}
}

public void startLineTracking() {
private void startLineTracking() {
_editor.removeTextChangedListener(_lineTrackingWatcher);
_maxNumber = 1;
final CharSequence text = _editor.getText();
if (text != null) {
_maxNumber += countChar(text, 0, text.length(), '\n');
_maxNumber += countLines(text, 0, text.length());
}
_editor.addTextChangedListener(_lineTrackingWatcher);
}

public void stopLineTracking() {
private void stopLineTracking() {
_editor.removeTextChangedListener(_lineTrackingWatcher);
}

public void prepare() {
startLineTracking();
_textView.setVisibility(VISIBLE);
}

public void updateState() {
// If text size or the max line number of digits changed, update related variables
if (isTextSizeChanged() || isMaxNumberDigitsChanged()) {
_numberX = LINE_NUMBER_PADDING_LEFT + (int) _paint.measureText(String.valueOf(_maxNumber));
_gutterX = _numberX + LINE_NUMBER_PADDING_RIGHT;
_textView.setWidth(_gutterX + 1);
}
}

/**
* Draw line numbers.
*
Expand All @@ -187,13 +194,7 @@ public void draw(final Canvas canvas) {
return;
}

// If text size or the max line number of digits changed,
// update the variables and reset padding
if (isTextSizeChanged() || isMaxNumberDigitsChanged()) {
_numberX = LINE_NUMBER_PADDING_LEFT + (int) _paint.measureText(String.valueOf(_maxNumber));
_gutterX = _numberX + LINE_NUMBER_PADDING_RIGHT;
_editor.setPadding(_gutterX + 12, _editor.getPaddingTop(), _editor.getPaddingRight(), _editor.getPaddingBottom());
}
updateState();

int i = _startLine[0], number = _startLine[1];
// If current visible area is out of current line numbers area,
Expand Down Expand Up @@ -230,10 +231,12 @@ public void draw(final Canvas canvas) {
}

/**
* Reset to the state without line numbers.
* Stop drawing line numbers and reset states.
*/
public void reset() {
_editor.setPadding(_defaultPaddingLeft, _editor.getPaddingTop(), _editor.getPaddingRight(), _editor.getPaddingBottom());
public void stop() {
stopLineTracking();
_textView.setWidth(0);
_textView.setVisibility(GONE);
_maxNumberDigits = 0;
}
}
Expand Down
48 changes: 31 additions & 17 deletions src/main/res/layout/edit.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/vscroll"
android:layout_width="match_parent"
Expand All @@ -10,22 +9,37 @@
android:layout_marginBottom="8dp"
android:fillViewport="true">

<HorizontalScrollView
android:id="@+id/hscroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
tools:ignore="LabelFor">

<org.billthefarmer.editor.NewEditText
android:id="@+id/text"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top"
android:inputType="text|textMultiLine"
android:typeface="monospace"
tools:ignore="Autofill" />
android:orientation="horizontal">

<org.billthefarmer.editor.LineNumbersTextView
android:id="@+id/lineNumbersView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0"
android:text="" />

<HorizontalScrollView
android:id="@+id/hscroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:fillViewport="true"
tools:ignore="LabelFor">

<EditText
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="top"
android:inputType="text|textMultiLine"
android:typeface="monospace"
tools:ignore="Autofill" />

</HorizontalScrollView>

</HorizontalScrollView>
</LinearLayout>

</ScrollView>
2 changes: 1 addition & 1 deletion src/main/res/layout/wrap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
android:fillViewport="true"
tools:ignore="LabelFor">

<org.billthefarmer.editor.NewEditText
<EditText
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand Down
Loading

0 comments on commit c86bc4d

Please sign in to comment.