package com.fastaccess.ui.widgets;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.support.v4.text.TextUtilsCompat;
import android.support.v4.view.ViewCompat;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.ReplacementSpan;
import com.fastaccess.helper.ViewHelper;
import java.util.Locale;
/**
* adopted class from Android source code & modified to fit FastHub need.
*/
public class LabelSpan extends ReplacementSpan {
public interface SpanDimensions {
int getPadding();
int getPaddingExtraWidth();
int getPaddingAfter();
int getMaxWidth();
float getRoundedCornerRadius();
int getMarginTop();
boolean isRtl();
}
private final TextPaint txtPaint = new TextPaint();
private final FontMetricsInt fontMetrics = new FontMetricsInt();
private final int color;
private final SpanDimensions dims;
public LabelSpan(int color, @NonNull SpanDimensions dims) {
this.color = color;
txtPaint.bgColor = color;
this.dims = dims;
}
public LabelSpan(int color) {
this(color, new SpanDimensions() {
@Override public int getPadding() {
return 6;
}
@Override public int getPaddingExtraWidth() {
return 0;
}
@Override public int getPaddingAfter() {
return 0;
}
@Override public int getMaxWidth() {
return 1000;//random number
}
@Override public float getRoundedCornerRadius() {
return 5;
}
@Override public int getMarginTop() {
return 8;
}
@Override public boolean isRtl() {
return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;
}
});
}
@Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
setupFontMetrics(text, start, end, fm, paint);
if (fm != null) {
final int padding = dims.getPadding();
final int margin = dims.getMarginTop();
fm.ascent = Math.min(fm.top, fm.ascent - padding) - margin;
fm.descent = Math.max(fm.bottom, padding);
fm.top = fm.ascent;
fm.bottom = fm.descent;
}
return measureWidth(txtPaint, text, start, end, dims.isRtl());
}
private int measureWidth(Paint paint, CharSequence text, int start, int end,
boolean includePaddingAfter) {
final int paddingW = dims.getPadding() + dims.getPaddingExtraWidth();
final int maxWidth = dims.getMaxWidth();
int w = (int) paint.measureText(text, start, end) + 2 * paddingW;
if (includePaddingAfter) {
w += dims.getPaddingAfter();
}
if (w > maxWidth) {
w = maxWidth;
}
return w;
}
private void setupFontMetrics(CharSequence text, int start, int end, FontMetricsInt fm, Paint p) {
txtPaint.set(p);
final CharacterStyle[] otherSpans = ((Spanned) text).getSpans(start, end, CharacterStyle.class);
for (CharacterStyle otherSpan : otherSpans) {
otherSpan.updateDrawState(txtPaint);
}
txtPaint.setTextSize(p.getTextSize());
if (fm != null) {
txtPaint.getFontMetricsInt(fm);
}
}
@Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end,
float x, int top, int y, int bottom, @NonNull Paint paint) {
final int padding = dims.getPadding();
final int paddingW = padding + dims.getPaddingExtraWidth();
final int maxWidth = dims.getMaxWidth();
setupFontMetrics(text, start, end, fontMetrics, paint);
final int bgWidth = measureWidth(txtPaint, text, start, end, false);
fontMetrics.top = Math.min(fontMetrics.top, fontMetrics.ascent - padding);
fontMetrics.bottom = Math.max(fontMetrics.bottom, padding);
top = y + fontMetrics.top - fontMetrics.bottom;
bottom = y;
y = bottom - fontMetrics.bottom;
final boolean isRtl = dims.isRtl();
final int paddingAfter = dims.getPaddingAfter();
if (txtPaint.bgColor != 0) {
final int prevColor = txtPaint.getColor();
final Paint.Style prevStyle = txtPaint.getStyle();
txtPaint.setColor(txtPaint.bgColor);
txtPaint.setStyle(Paint.Style.FILL);
final float left;
if (isRtl) {
left = x + paddingAfter;
} else {
left = x;
}
final float right = left + bgWidth;
final RectF rect = new RectF(left, top, right, bottom);
final float radius = dims.getRoundedCornerRadius();
canvas.drawRoundRect(rect, radius, radius, txtPaint);
txtPaint.setColor(prevColor);
txtPaint.setStyle(prevStyle);
}
if (bgWidth == maxWidth) {
text = TextUtils.ellipsize(text.subSequence(start, end).toString(), txtPaint, bgWidth - 2 * paddingW, TextUtils.TruncateAt.MIDDLE);
start = 0;
end = text.length();
}
float textX = x + paddingW;
if (isRtl) {
textX += paddingAfter;
}
if (color != Color.TRANSPARENT) txtPaint.setColor(ViewHelper.generateTextColor(color));
canvas.drawText(text, start, end, textX, y, txtPaint);
}
}