Skip to content

Commit

Permalink
Rework single pass line numbering
Browse files Browse the repository at this point in the history
  • Loading branch information
harshad1 committed Aug 14, 2023
1 parent 8f18b61 commit d38bef6
Showing 1 changed file with 33 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
import net.gsantner.opoc.wrapper.GsCallback;
import net.gsantner.opoc.wrapper.GsTextWatcherAdapter;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("UnusedReturnValue")
public class HighlightingEditor extends AppCompatEditText {

Expand Down Expand Up @@ -65,7 +68,7 @@ public class HighlightingEditor extends AppCompatEditText {
private static final int LINE_NUMBERS_PADDING_RIGHT = 10;
private final Rect _numRect;

private int _numXPos = -1; // X coordinate for drawing numbers
private final List<Integer> _numYPositions; // Y positions of numbers to draw

public HighlightingEditor(Context context, AttributeSet attrs) {
super(context, attrs);
Expand All @@ -84,6 +87,7 @@ public HighlightingEditor(Context context, AttributeSet attrs) {
_oldHlRect = new Rect();
_hlRect = new Rect();
_numRect = new Rect();
_numYPositions = new ArrayList<>();

addTextChangedListener(new GsTextWatcherAdapter() {

Expand All @@ -92,7 +96,6 @@ public void onTextChanged(CharSequence s, int start, int before, int count) {
if (_hlEnabled && _hl != null) {
_hl.fixup(start, before, count);
}
_numXPos = -1;
}

@Override
Expand Down Expand Up @@ -157,40 +160,40 @@ private void drawLineNumbers(final Canvas canvas) {
final int offsetY = getPaddingTop();
final int maxLayoutLine = layout.getLineCount();

// Set gutter size and padding
// Only update if needed
final int lineX;
if (_numXPos < 0) {
final int lineCount = TextViewUtils.countChar(text, '\n');
final int width = Math.round(_paint.measureText(String.valueOf(lineCount)));
_numXPos = LINE_NUMBERS_PADDING_LEFT + width;

lineX = _numXPos + LINE_NUMBERS_PADDING_RIGHT;
setPadding( lineX + 10, getPaddingTop(), getPaddingRight(), getPaddingBottom());
} else {
lineX = _numXPos + LINE_NUMBERS_PADDING_RIGHT;
// We make a single pass through the text to determine
// 1. y positions and line numbers we want to draw
// 2. max line number (to gauge gutter width)
_numYPositions.clear();
int startNumber = 1, maxNumber = 1;
for (int i = 0; i < maxLayoutLine; i++) {
final int start = layout.getLineStart(i);
if (start == 0 || text.charAt(start - 1) == '\n') {
final int numY = layout.getLineBaseline(i);
if (numY < top) {
startNumber++;
} else if (numY < bottom) {
_numYPositions.add(numY);
}
maxNumber++;
}
}

// Draw the right border
// Draw the gutter
final int width = Math.round(_paint.measureText(String.valueOf(maxNumber)));
final int numX = LINE_NUMBERS_PADDING_LEFT + width;
final int lineX = numX + LINE_NUMBERS_PADDING_RIGHT;
final int padding = lineX + 10;
if (padding != getPaddingLeft()) {
setPadding(padding, getPaddingTop(), getPaddingRight(), getPaddingBottom());
}
_paint.setColor(Color.LTGRAY);
canvas.drawLine(lineX, top, lineX, bottom, _paint);

// Draw the numbers
int line = 0;
int number = 1;
int yPos = top;
_paint.setColor(Color.GRAY);

while(line < maxLayoutLine && yPos < bottom) {
final int start = layout.getLineStart(line);
if (start == 0 || text.charAt(start - 1) == '\n') {
yPos = layout.getLineBounds(line, null);
if (yPos > top) {
canvas.drawText(String.valueOf(number), _numXPos, yPos + offsetY, _paint);
}
number++;
}
line++;
for (int i = 0; i < _numYPositions.size(); i++) {
final String number = String.valueOf(startNumber + i);
final float numY = _numYPositions.get(i) + offsetY;
canvas.drawText(number, numX, numY, _paint);
}
}

Expand Down

0 comments on commit d38bef6

Please sign in to comment.