feat: current line highlight

This commit is contained in:
hyb1996 2018-02-24 12:05:05 +08:00
parent 198a694064
commit dab33831cb
7 changed files with 101 additions and 42 deletions

View File

@ -4,10 +4,10 @@
"colors": {
"editor.background": "#1E1E1E",
"editor.foreground": "#D4D4D4",
"lineNumber.foreground": "#404040",
"editorLineNumber.foreground": "#404040",
"imeBar.background": "#dd1e1e1e",
"imeBar.foreground": "#f1f1f1",
"editor.selectionHighlightBackground": "#ADD6FF26"
"editor.lineHighlightBackground": "#2e2e35"
},
"tokenColors": [
{

View File

@ -483,9 +483,11 @@
"colors": {
"imeBar.background": "#ddf0f1f2",
"imeBar.foreground": "#222327",
"lineNumber.foreground": "#9DA39A",
"editorLineNumber.foreground": "#9DA39A",
"editor.background": "#F5F5F5",
"editor.foreground": "#000000",
"editor.lineHighlightBackground": "#E4F6D4",
"focusBorder": "#A6B39B",
"pickerGroup.foreground": "#A6B39B",
"pickerGroup.border": "#749351",
@ -497,12 +499,10 @@
"list.highlightForeground": "#9769dc",
"selection.background": "#C9D0D9",
"editorWhitespace.foreground": "#AAAAAA",
"editor.lineHighlightBackground": "#E4F6D4",
"editor.selectionBackground": "#C9D0D9",
"panel.background": "#F5F5F5",
"sideBar.background": "#F2F2F2",
"sideBarSectionHeader.background": "#ede8ef",
"editorLineNumber.foreground": "#9DA39A",
"editorCursor.foreground": "#54494B",
"inputOption.activeBorder": "#adafb7",
"dropdown.background": "#F5F5F5",

View File

@ -12,7 +12,7 @@ public class EditorColors {
private String mEditorForeground;
@SerializedName("editor.inactiveSelectionBackground")
private String mEditorInactiveSelectionBackground;
@SerializedName("lineNumber.foreground")
@SerializedName("editorLineNumber.foreground")
private String mLineNumberForeground;
@SerializedName("editor.selectionHighlightBackground")
private String mEditorSelectionHighlightBackground;
@ -20,6 +20,16 @@ public class EditorColors {
private String mImeBackgroundColor;
@SerializedName("imeBar.foreground")
private String mImeForegroundColor;
@SerializedName("editor.lineHighlightBackground")
private String mLineHighlightBackground;
public String getLineHighlightBackground() {
return mLineHighlightBackground;
}
public void setLineHighlightBackground(String lineHighlightBackground) {
mLineHighlightBackground = lineHighlightBackground;
}
public String getEditorBackground() {
return mEditorBackground;

View File

@ -24,7 +24,6 @@ import android.graphics.Paint;
import android.graphics.Typeface;
import android.support.v7.widget.AppCompatEditText;
import android.text.Layout;
import android.text.method.ScrollingMovementMethod;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TimingLogger;
@ -50,6 +49,8 @@ public class CodeEditText extends AppCompatEditText {
private volatile JavaScriptHighlighter.HighlightTokens mHighlightTokens;
private Theme mTheme;
private TimingLogger mLogger = new TimingLogger(LOG_TAG, "draw");
private Paint mLineHighlightPaint = new Paint();
private int mFirstLineForDraw = -1, mLastLineForDraw;
public CodeEditText(Context context) {
super(context);
@ -71,6 +72,7 @@ public class CodeEditText extends AppCompatEditText {
setTypeface(Typeface.MONOSPACE);
setHorizontallyScrolling(true);
mTheme = Theme.getDefault(getContext());
mLineHighlightPaint.setStyle(Paint.Style.FILL);
}
public void setTheme(Theme theme) {
@ -84,39 +86,57 @@ public class CodeEditText extends AppCompatEditText {
if (mParentScrollView == null) {
mParentScrollView = (HVScrollView) getParent();
}
updatePaddingForGutter();
updateLineRangeForDraw(canvas);
//绘制当前行高亮需要在绘制光标之前
drawLineHighlight(canvas, mLineHighlightPaint, getCurrentLine());
//调用super.onDraw绘制光标和选择高亮因为字体颜色被设置为透明因此super.onDraw()绘制的字体不显示
// TODO: 2018/2/24 优化效率不绘制透明字体
super.onDraw(canvas);
mLogger.addSplit("super draw");
canvas.save();
canvas.translate(0, getExtendedPaddingTop());
drawText(canvas);
mLogger.addSplit("draw text");
canvas.restore();
mLogger.dumpToLog();
}
private void updateLineRangeForDraw(Canvas canvas) {
Layout layout = getLayout();
if (layout == null)
return;
long lineRange = getLineRangeForDraw(layout, canvas);
mFirstLineForDraw = LayoutHelper.unpackRangeStartFromLong(lineRange);
mLastLineForDraw = LayoutHelper.unpackRangeEndFromLong(lineRange);
}
private void updatePaddingForGutter() {
// 根据行号计算左边距padding 留出绘制行号的空间
String max = Integer.toString(getLineCount());
float gutterWidth = getPaint().measureText(max) + 20;
if (getPaddingLeft() != gutterWidth) {
setPadding((int) gutterWidth, 0, 0, 0);
}
super.onDraw(canvas);
mLogger.addSplit("super draw");
// 画文字
canvas.save();
canvas.translate(0, getExtendedPaddingTop());
drawText(canvas);
mLogger.addSplit("draw text");
canvas.restore();
mLogger.dumpToLog();
}
// 绘制文本着色
private void drawText(Canvas canvas) {
JavaScriptHighlighter.HighlightTokens highlightTokens = mHighlightTokens;
Layout layout = getLayout();
long lineRange = getLineRangeForDraw(layout, canvas);
int firstLineForDraw = LayoutHelper.unpackRangeStartFromLong(lineRange);
int lastLineForDraw = LayoutHelper.unpackRangeEndFromLong(lineRange);
if (firstLineForDraw < 0) {
if (mFirstLineForDraw < 0) {
return;
}
JavaScriptHighlighter.HighlightTokens highlightTokens = mHighlightTokens;
Layout layout = getLayout();
int lineCount = getLineCount();
int paddingLeft = getPaddingLeft();
Paint paint = getPaint();
if (DEBUG)
Log.d(LOG_TAG, "draw line: " + (lastLineForDraw - firstLineForDraw + 1));
for (int line = firstLineForDraw; line <= lastLineForDraw && line < lineCount; line++) {
Log.d(LOG_TAG, "draw line: " + (mLastLineForDraw - mFirstLineForDraw + 1));
for (int line = mFirstLineForDraw; line <= mLastLineForDraw && line < lineCount; line++) {
int lineBottom = layout.getLineTop(line + 1);
int lineBaseline = lineBottom - layout.getLineDescent(line);
@ -128,6 +148,23 @@ public class CodeEditText extends AppCompatEditText {
}
}
private void drawLineHighlight(Canvas canvas, Paint paint, int line) {
if (line < mFirstLineForDraw || line > mLastLineForDraw || mFirstLineForDraw < 0 || line < 0) {
return;
}
int lineTop = getLayout().getLineTop(line);
int lineBottom = getLayout().getLineTop(line + 1);
paint.setColor(mTheme.getLineHighlightBackgroundColor());
canvas.drawRect(0, lineTop, canvas.getWidth(), lineBottom, paint);
}
private int getCurrentLine() {
Layout layout = getLayout();
if (layout == null)
return -1;
return LayoutHelper.getLineOfChar(getLayout(), getSelectionStart());
}
private void drawCode(Canvas canvas, Paint paint, int paddingLeft, int line, Layout layout, int lineBaseline, JavaScriptHighlighter.HighlightTokens highlightTokens) {
int lineStart = layout.getLineStart(line);
if (lineStart >= mHighlightTokens.getText().length()) {

View File

@ -80,7 +80,7 @@ public class CodeEditor extends HVScrollView {
}
public void copyLine() {
int line = getLineOfChar(mCodeEditText.getSelectionStart());
int line = LayoutHelper.getLineOfChar(mCodeEditText.getLayout(), mCodeEditText.getSelectionStart());
if (line < 0 || line >= mCodeEditText.getLayout().getLineCount())
return;
CharSequence lineText = mCodeEditText.getText().subSequence(mCodeEditText.getLayout().getLineStart(line),
@ -89,23 +89,9 @@ public class CodeEditor extends HVScrollView {
Snackbar.make(this, R.string.text_already_copy_to_clip, Snackbar.LENGTH_SHORT).show();
}
private int getLineOfChar(int i) {
int low = 0;
int high = mCodeEditText.getLineCount() - 1;
while (low < high) {
int mid = (low + high) >>> 1;
int midVal = mCodeEditText.getLayout().getLineEnd(mid);
if (midVal <= i)
low = mid + 1;
else if (midVal > i)
high = mid - 1;
}
return low;
}
public void deleteLine() {
int line = getLineOfChar(mCodeEditText.getSelectionStart());
int line = LayoutHelper.getLineOfChar(mCodeEditText.getLayout(), mCodeEditText.getSelectionStart());
if (line < 0 || line >= mCodeEditText.getLayout().getLineCount())
return;
mCodeEditText.getText().replace(mCodeEditText.getLayout().getLineStart(line),
@ -121,14 +107,14 @@ public class CodeEditor extends HVScrollView {
}
public void jumpToLineStart() {
int line = getLineOfChar(mCodeEditText.getSelectionStart());
int line = LayoutHelper.getLineOfChar(mCodeEditText.getLayout(), mCodeEditText.getSelectionStart());
if (line < 0 || line >= mCodeEditText.getLayout().getLineCount())
return;
mCodeEditText.setSelection(mCodeEditText.getLayout().getLineStart(line));
}
public void jumpToLineEnd() {
int line = getLineOfChar(mCodeEditText.getSelectionStart());
int line = LayoutHelper.getLineOfChar(mCodeEditText.getLayout(), mCodeEditText.getSelectionStart());
if (line < 0 || line >= mCodeEditText.getLayout().getLineCount())
return;
mCodeEditText.setSelection(mCodeEditText.getLayout().getLineEnd(line) - 1);

View File

@ -1,5 +1,6 @@
package com.stardust.scriptdroid.ui.edit.editor;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.text.Layout;
@ -51,4 +52,23 @@ public class LayoutHelper {
return (int) (range & 0x00000000FFFFFFFFL);
}
public static int getLineOfChar(Layout layout, int charIndex) {
int low = 0;
int high = layout.getLineCount() - 1;
while (low < high) {
int mid = (low + high) >>> 1;
int midVal = layout.getLineEnd(mid);
if (charIndex > midVal) {
low = mid + 1;
} else if (charIndex < midVal) {
high = mid;
} else {
return Math.min(layout.getLineCount() - 1, mid + 1);
}
}
return low;
}
}

View File

@ -24,6 +24,7 @@ public class Theme {
private int mImeBarBackgroundColor = 0xDDFFFFFF;
private int mImeBarForegroundColor = Color.WHITE;
private EditorTheme mEditorTheme;
private int mLineHighlightBackground;
public Theme(EditorTheme theme) {
mEditorTheme = theme;
@ -32,6 +33,7 @@ public class Theme {
mLineNumberColor = parseColor(theme.getEditorColors().getLineNumberForeground(), mLineNumberColor);
mImeBarBackgroundColor = parseColor(theme.getEditorColors().getImeBackgroundColor(), mImeBarBackgroundColor);
mImeBarForegroundColor = parseColor(theme.getEditorColors().getImeForegroundColor(), mImeBarForegroundColor);
mLineHighlightBackground = parseColor(theme.getEditorColors().getLineHighlightBackground(), mLineHighlightBackground);
for (TokenColor tokenColor : theme.getTokenColors()) {
String foregroundStr = tokenColor.getSettings().getForeground();
@ -120,6 +122,10 @@ public class Theme {
mImeBarForegroundColor = imeBarForegroundColor;
}
public int getLineHighlightBackgroundColor() {
return mLineHighlightBackground;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;