2022-04-25 07:42:52 +02:00
|
|
|
package org.mian.gitnex.views;
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2021-04-13 20:56:50 +02:00
|
|
|
import android.app.Activity;
|
2021-03-21 19:26:28 +01:00
|
|
|
import android.content.Context;
|
|
|
|
import android.graphics.Canvas;
|
|
|
|
import android.graphics.Paint;
|
|
|
|
import android.graphics.Rect;
|
|
|
|
import android.graphics.Typeface;
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
import android.util.TypedValue;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.HorizontalScrollView;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.ColorInt;
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
2022-09-21 07:43:00 +02:00
|
|
|
import org.mian.gitnex.core.MainGrammarLocator;
|
|
|
|
import org.mian.gitnex.helpers.AppUtil;
|
2022-09-30 05:04:01 +02:00
|
|
|
import org.mian.gitnex.helpers.codeeditor.markwon.SyntaxHighlighter;
|
|
|
|
import org.mian.gitnex.helpers.codeeditor.theme.Theme;
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author opyale
|
|
|
|
*/
|
|
|
|
public class SyntaxHighlightedArea extends LinearLayout {
|
|
|
|
|
2022-09-30 05:04:01 +02:00
|
|
|
private Theme theme;
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
private TextView sourceView;
|
|
|
|
private LinesView linesView;
|
|
|
|
|
|
|
|
public SyntaxHighlightedArea(@NonNull Context context) {
|
|
|
|
super(context);
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
public SyntaxHighlightedArea(@NonNull Context context, @Nullable AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
2022-09-21 07:43:00 +02:00
|
|
|
public SyntaxHighlightedArea(
|
|
|
|
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
2021-03-21 19:26:28 +01:00
|
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setup() {
|
|
|
|
|
2022-09-30 05:04:01 +02:00
|
|
|
theme = Theme.getDefaultTheme(getContext());
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
sourceView = new TextView(getContext());
|
|
|
|
|
2022-09-21 07:43:00 +02:00
|
|
|
sourceView.setLayoutParams(
|
|
|
|
new ViewGroup.LayoutParams(
|
|
|
|
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
|
|
sourceView.setTypeface(
|
|
|
|
Typeface.createFromAsset(
|
|
|
|
getContext().getAssets(), "fonts/sourcecodeproregular.ttf"));
|
2021-04-13 20:56:50 +02:00
|
|
|
sourceView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
|
2022-09-30 05:04:01 +02:00
|
|
|
sourceView.setTextColor(
|
|
|
|
getContext().getResources().getColor(theme.getDefaultColor(), null));
|
2021-04-13 20:56:50 +02:00
|
|
|
sourceView.setTextIsSelectable(true);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
int padding = AppUtil.getPixelsFromDensity(getContext(), 5);
|
|
|
|
sourceView.setPadding(padding, 0, padding, 0);
|
|
|
|
|
|
|
|
HorizontalScrollView horizontalScrollView = new HorizontalScrollView(getContext());
|
2022-09-21 07:43:00 +02:00
|
|
|
horizontalScrollView.setLayoutParams(
|
|
|
|
new LinearLayout.LayoutParams(
|
|
|
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
2021-03-21 19:26:28 +01:00
|
|
|
horizontalScrollView.addView(sourceView);
|
|
|
|
|
|
|
|
linesView = new LinesView(getContext());
|
|
|
|
|
2022-09-21 07:43:00 +02:00
|
|
|
linesView.setLayoutParams(
|
|
|
|
new LinearLayout.LayoutParams(
|
|
|
|
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
|
|
linesView.setPadding(
|
|
|
|
AppUtil.getPixelsFromDensity(getContext(), 3),
|
|
|
|
0,
|
|
|
|
AppUtil.getPixelsFromDensity(getContext(), 6),
|
|
|
|
0);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
linesView.getPaint().setTypeface(sourceView.getTypeface());
|
|
|
|
linesView.getPaint().setTextSize(sourceView.getTextSize());
|
|
|
|
|
2022-09-30 05:04:01 +02:00
|
|
|
linesView.setBackgroundColor(
|
|
|
|
getContext().getResources().getColor(theme.getBackgroundColor(), null));
|
|
|
|
linesView.setTextColor(getContext().getResources().getColor(theme.getDefaultColor(), null));
|
|
|
|
linesView.setLineColor(getContext().getResources().getColor(theme.getDefaultColor(), null));
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
setOrientation(HORIZONTAL);
|
2022-09-30 05:04:01 +02:00
|
|
|
setBackgroundColor(getContext().getResources().getColor(theme.getBackgroundColor(), null));
|
2021-03-21 19:26:28 +01:00
|
|
|
addView(linesView);
|
|
|
|
addView(horizontalScrollView);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setContent(@NonNull String source, @NonNull String extension) {
|
|
|
|
|
2024-03-28 13:02:17 +01:00
|
|
|
if (!source.isEmpty()) {
|
2022-09-21 07:43:00 +02:00
|
|
|
|
|
|
|
Thread highlightingThread =
|
|
|
|
new Thread(
|
|
|
|
() -> {
|
|
|
|
try {
|
|
|
|
|
|
|
|
CharSequence highlightedSource =
|
2022-09-30 05:04:01 +02:00
|
|
|
SyntaxHighlighter.create(
|
|
|
|
getContext(),
|
|
|
|
theme,
|
2022-09-21 07:43:00 +02:00
|
|
|
MainGrammarLocator
|
|
|
|
.DEFAULT_FALLBACK_LANGUAGE)
|
|
|
|
.highlight(
|
2022-09-30 05:04:01 +02:00
|
|
|
MainGrammarLocator.fromExtension(
|
|
|
|
extension)
|
|
|
|
.toUpperCase(),
|
2022-09-21 07:43:00 +02:00
|
|
|
source);
|
|
|
|
|
|
|
|
getActivity()
|
|
|
|
.runOnUiThread(
|
|
|
|
() -> sourceView.setText(highlightedSource));
|
|
|
|
|
|
|
|
} catch (Throwable ignored) {
|
|
|
|
// Fall back to plaintext if something fails
|
|
|
|
getActivity().runOnUiThread(() -> sourceView.setText(source));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Thread lineCountingThread =
|
|
|
|
new Thread(
|
|
|
|
() -> {
|
|
|
|
long lineCount = AppUtil.getLineCount(source);
|
|
|
|
|
|
|
|
try {
|
|
|
|
highlightingThread.join();
|
|
|
|
} catch (InterruptedException ignored) {
|
|
|
|
}
|
|
|
|
|
|
|
|
getActivity()
|
|
|
|
.runOnUiThread(() -> linesView.setLineCount(lineCount));
|
|
|
|
});
|
2021-04-13 20:56:50 +02:00
|
|
|
|
|
|
|
highlightingThread.start();
|
|
|
|
lineCountingThread.start();
|
2021-03-21 19:26:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-13 20:56:50 +02:00
|
|
|
private Activity getActivity() {
|
|
|
|
return (Activity) getContext();
|
|
|
|
}
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
public String getContent() {
|
2021-03-21 19:26:28 +01:00
|
|
|
return sourceView.getText().toString();
|
2022-08-15 16:26:02 +02:00
|
|
|
}
|
2021-03-21 19:26:28 +01:00
|
|
|
|
|
|
|
private static class LinesView extends View {
|
|
|
|
|
|
|
|
private final Paint paint = new Paint();
|
|
|
|
private final Rect textBounds = new Rect();
|
|
|
|
|
2022-09-21 07:43:00 +02:00
|
|
|
@ColorInt private int backgroundColor;
|
|
|
|
@ColorInt private int textColor;
|
|
|
|
@ColorInt private int lineColor;
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2021-04-13 20:56:50 +02:00
|
|
|
private long lineCount;
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
public LinesView(Context context) {
|
|
|
|
super(context);
|
|
|
|
}
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2021-04-13 20:56:50 +02:00
|
|
|
public void setLineCount(long lineCount) {
|
2021-03-21 19:26:28 +01:00
|
|
|
this.lineCount = lineCount;
|
2021-04-13 20:56:50 +02:00
|
|
|
requestLayout();
|
2021-03-21 19:26:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setBackgroundColor(@ColorInt int backgroundColor) {
|
|
|
|
this.backgroundColor = backgroundColor;
|
2021-04-13 20:56:50 +02:00
|
|
|
invalidate();
|
2021-03-21 19:26:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setTextColor(@ColorInt int textColor) {
|
|
|
|
this.textColor = textColor;
|
2021-04-13 20:56:50 +02:00
|
|
|
invalidate();
|
2021-03-21 19:26:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setLineColor(@ColorInt int lineColor) {
|
|
|
|
this.lineColor = lineColor;
|
2021-04-13 20:56:50 +02:00
|
|
|
invalidate();
|
2021-03-21 19:26:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public Paint getPaint() {
|
|
|
|
return paint;
|
|
|
|
}
|
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
@Override
|
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
String highestLineNumber = String.valueOf(lineCount);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
paint.getTextBounds(highestLineNumber, 0, highestLineNumber.length(), textBounds);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-09-21 07:43:00 +02:00
|
|
|
setMeasuredDimension(
|
|
|
|
getPaddingLeft() + textBounds.width() + getPaddingRight(),
|
|
|
|
MeasureSpec.getSize(heightMeasureSpec));
|
2022-08-15 16:26:02 +02:00
|
|
|
}
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
@Override
|
|
|
|
protected void onDraw(Canvas canvas) {
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
paint.setColor(backgroundColor);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
float marginTopBottom = (float) (getHeight() - (textBounds.height() / 2)) / lineCount;
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
paint.setColor(textColor);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
canvas.save();
|
|
|
|
canvas.translate(getPaddingLeft(), marginTopBottom);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-09-21 07:43:00 +02:00
|
|
|
for (int currentLine = 1; currentLine <= lineCount; currentLine++) {
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
canvas.drawText(String.valueOf(currentLine), 0, 0, paint);
|
|
|
|
canvas.translate(0, marginTopBottom);
|
|
|
|
}
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
paint.setColor(lineColor);
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
int dividerX = getWidth() - 1;
|
|
|
|
int dividerY = getHeight();
|
2021-03-21 19:26:28 +01:00
|
|
|
|
2022-08-15 16:26:02 +02:00
|
|
|
canvas.restore();
|
|
|
|
canvas.drawLine(dividerX, 0, dividerX, dividerY, paint);
|
|
|
|
}
|
|
|
|
}
|
2021-03-21 19:26:28 +01:00
|
|
|
}
|