opt: draw only visible chars for a line
This commit is contained in:
@@ -8,8 +8,8 @@ android {
|
|||||||
applicationId "com.stardust.scriptdroid"
|
applicationId "com.stardust.scriptdroid"
|
||||||
minSdkVersion 17
|
minSdkVersion 17
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 250
|
versionCode 251
|
||||||
versionName "3.0.0 Alpha50"
|
versionName "3.1.0 Alpha"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
ndk {
|
ndk {
|
||||||
|
|||||||
@@ -23,11 +23,10 @@ import android.graphics.Color;
|
|||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.support.v7.widget.AppCompatEditText;
|
import android.support.v7.widget.AppCompatEditText;
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import com.stardust.scriptdroid.ui.edit.theme.Theme;
|
import com.stardust.scriptdroid.ui.edit.theme.Theme;
|
||||||
|
|
||||||
@@ -128,7 +127,9 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
int fontCount = 0;
|
int fontCount = 0;
|
||||||
int previousColor = mHighlightTokens.getCharColor(lineStart);
|
int previousColor = mHighlightTokens.getCharColor(lineStart);
|
||||||
int previousColorPos = lineStart;
|
int previousColorPos = lineStart;
|
||||||
for (int i = lineStart; i < lineEnd; i++) {
|
int visibleCharStart = getVisibleCharIndex(paint, getScrollX(), lineStart, lineEnd);
|
||||||
|
int visibleCharEnd = getVisibleCharIndex(paint, getScrollX() + getWidth(), lineStart, lineEnd) + 1;
|
||||||
|
for (int i = visibleCharStart; i < visibleCharEnd && i < lineEnd; i++) {
|
||||||
fontCount++;
|
fontCount++;
|
||||||
int color = mHighlightTokens.getCharColor(i);
|
int color = mHighlightTokens.getCharColor(i);
|
||||||
if (previousColor != color) {
|
if (previousColor != color) {
|
||||||
@@ -137,13 +138,30 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
previousColorPos = i;
|
previousColorPos = i;
|
||||||
fontCount = 1;
|
fontCount = 1;
|
||||||
}
|
}
|
||||||
if (i == lineEnd - 1) {
|
if (i == visibleCharEnd - 1) {
|
||||||
drawText(canvas, paint, paddingLeft, lineBaseline, lineStart, previousColorPos, previousColorPos + fontCount, previousColor);
|
drawText(canvas, paint, paddingLeft, lineBaseline, lineStart, previousColorPos, previousColorPos + fontCount, previousColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getVisibleCharIndex(Paint paint, int x, int lineStart, int lineEnd) {
|
||||||
|
if (x == 0)
|
||||||
|
return lineStart;
|
||||||
|
int low = lineStart;
|
||||||
|
int high = lineEnd - 1;
|
||||||
|
while (low < high) {
|
||||||
|
int mid = (high + low) >>> 1;
|
||||||
|
float midX = paint.measureText(getText(), lineStart, mid + 1);
|
||||||
|
if (x < midX) {
|
||||||
|
high = mid - 1;
|
||||||
|
} else {
|
||||||
|
low = mid + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
|
||||||
private void drawText(Canvas canvas, Paint paint, int paddingLeft, int lineBaseline, int lineStart, int start, int end, int color) {
|
private void drawText(Canvas canvas, Paint paint, int paddingLeft, int lineBaseline, int lineStart, int start, int end, int color) {
|
||||||
if (start >= end) {
|
if (start >= end) {
|
||||||
return;
|
return;
|
||||||
@@ -162,16 +180,23 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
|
|
||||||
private long getLineRangeForDraw(Layout layout, Canvas canvas) {
|
private long getLineRangeForDraw(Layout layout, Canvas canvas) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
float clipTop = (mScrollView.getScrollY() == 0) ? 0
|
int scrollY = getRealScrollY();
|
||||||
: getExtendedPaddingTop() + mScrollView.getScrollY()
|
float clipTop = (scrollY == 0) ? 0
|
||||||
|
: getExtendedPaddingTop() + scrollY
|
||||||
- mScrollView.getPaddingTop();
|
- mScrollView.getPaddingTop();
|
||||||
canvas.clipRect(0, clipTop, getWidth(), mScrollView.getScrollY()
|
canvas.clipRect(0, clipTop, getWidth(), scrollY
|
||||||
+ mScrollView.getHeight());
|
+ mScrollView.getHeight());
|
||||||
long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas);
|
long lineRangeForDraw = LayoutHelper.getLineRangeForDraw(layout, canvas);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
return lineRangeForDraw;
|
return lineRangeForDraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getRealScrollY() {
|
||||||
|
int scrollY = mScrollView.getScrollY();
|
||||||
|
View parent = (View) mScrollView.getParent();
|
||||||
|
return scrollY + parent.getScrollY();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSelectionChanged(int selStart, int selEnd) {
|
protected void onSelectionChanged(int selStart, int selEnd) {
|
||||||
super.onSelectionChanged(selStart, selEnd);
|
super.onSelectionChanged(selStart, selEnd);
|
||||||
@@ -206,7 +231,6 @@ public class CodeEditText extends AppCompatEditText {
|
|||||||
|
|
||||||
public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) {
|
public void updateHighlightTokens(JavaScriptHighlighter.HighlightTokens highlightTokens) {
|
||||||
mHighlightTokens = highlightTokens;
|
mHighlightTokens = highlightTokens;
|
||||||
Log.d(LOG_TAG, "tokens = " + highlightTokens);
|
postInvalidate();
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,41 @@ import io.reactivex.Observable;
|
|||||||
*/
|
*/
|
||||||
public class CodeEditor extends HVScrollView {
|
public class CodeEditor extends HVScrollView {
|
||||||
|
|
||||||
|
public interface CursorChangeCallback {
|
||||||
|
|
||||||
|
void onCursorChange(String line, int ch);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private CharSequence mReplacement = "";
|
private CharSequence mReplacement = "";
|
||||||
private String mKeywords;
|
private String mKeywords;
|
||||||
private int mFoundIndex = -1;
|
private int mFoundIndex = -1;
|
||||||
|
private CodeEditText mCodeEditText;
|
||||||
|
private PreformEdit mPreformEdit;
|
||||||
|
private JavaScriptHighlighter mJavaScriptHighlighter;
|
||||||
|
private Theme mTheme;
|
||||||
|
|
||||||
|
public CodeEditor(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeEditor(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
setFillViewport(true);
|
||||||
|
inflate(getContext(), R.layout.code_editor, this);
|
||||||
|
mCodeEditText = (CodeEditText) findViewById(R.id.code_edit_text);
|
||||||
|
mPreformEdit = new PreformEdit(mCodeEditText);
|
||||||
|
mJavaScriptHighlighter = new JavaScriptHighlighter(mTheme, mCodeEditText);
|
||||||
|
setTheme(Theme.getDefault(getContext()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public Observable<Integer> getLineCount() {
|
public Observable<Integer> getLineCount() {
|
||||||
return Observable.just(mCodeEditText.getLayout().getLineCount());
|
return Observable.just(mCodeEditText.getLayout().getLineCount());
|
||||||
@@ -100,39 +131,6 @@ public class CodeEditor extends HVScrollView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface CursorChangeCallback {
|
|
||||||
|
|
||||||
void onCursorChange(String line, int ch);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private CodeEditText mCodeEditText;
|
|
||||||
private PreformEdit mPreformEdit;
|
|
||||||
private JavaScriptHighlighter mJavaScriptHighlighter;
|
|
||||||
private Theme mTheme;
|
|
||||||
|
|
||||||
public CodeEditor(Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CodeEditor(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
setFillViewport(true);
|
|
||||||
inflate(getContext(), R.layout.code_editor, this);
|
|
||||||
mCodeEditText = (CodeEditText) findViewById(R.id.code_edit_text);
|
|
||||||
mPreformEdit = new PreformEdit(mCodeEditText);
|
|
||||||
mJavaScriptHighlighter = new JavaScriptHighlighter(mTheme, mCodeEditText);
|
|
||||||
setTheme(Theme.getDefault(getContext()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTheme(Theme theme) {
|
public void setTheme(Theme theme) {
|
||||||
mTheme = theme;
|
mTheme = theme;
|
||||||
mJavaScriptHighlighter.setTheme(theme);
|
mJavaScriptHighlighter.setTheme(theme);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
|||||||
|
|
||||||
private int[] mColors;
|
private int[] mColors;
|
||||||
private String mText;
|
private String mText;
|
||||||
|
private int mCount;
|
||||||
|
|
||||||
public HighlightTokens(String text) {
|
public HighlightTokens(String text) {
|
||||||
mColors = new int[text.length()];
|
mColors = new int[text.length()];
|
||||||
@@ -40,6 +41,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
|||||||
for (int i = tokenStart; i < tokenEnd; i++) {
|
for (int i = tokenStart; i < tokenEnd; i++) {
|
||||||
mColors[i] = color;
|
mColors[i] = color;
|
||||||
}
|
}
|
||||||
|
mCount = tokenEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -50,7 +52,7 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getCharCount() {
|
public int getCharCount() {
|
||||||
return mColors.length;
|
return mCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
@@ -101,9 +103,10 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
|
|||||||
int color = mTheme.getColorForToken(token);
|
int color = mTheme.getColorForToken(token);
|
||||||
highlightTokens.addToken(ts.getTokenBeg(), ts.getTokenEnd(), color);
|
highlightTokens.addToken(ts.getTokenBeg(), ts.getTokenEnd(), color);
|
||||||
}
|
}
|
||||||
|
if (highlightTokens.getCharCount() < sourceString.length()) {
|
||||||
|
highlightTokens.addToken(highlightTokens.getCharCount(), sourceString.length(), mTheme.getColorForToken(Token.NAME));
|
||||||
|
}
|
||||||
mCodeEditText.updateHighlightTokens(highlightTokens);
|
mCodeEditText.updateHighlightTokens(highlightTokens);
|
||||||
Log.d("Highlighter", "code = " + sourceString);
|
|
||||||
Log.d("Highlighter", "tokens = " + highlightTokens);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user