package com.bluejamesbond.text; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.text.Spannable; import android.text.SpannableString; import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.Toast; import com.bluejamesbond.text.hyphen.IHyphenator; import com.bluejamesbond.text.style.TextAlignment; /* * Copyright 2015 Mathew Kurian * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * IDocumentLayout.java * @author Mathew Kurian * * From TextJustify-Android Library v2.0 * https://github.com/bluejamesbond/TextJustify-Android * * Please report any issues * https://github.com/bluejamesbond/TextJustify-Android/issues * * Date: 1/27/15 3:35 AM */ @SuppressWarnings("unused") public abstract class IDocumentLayout { // Main content protected CharSequence text; protected int lineCount; protected int measuredHeight; protected boolean textChange; protected LayoutParams params; protected TextPaint paint; private Toast toast; private DisplayMetrics displayMetrics; @SuppressLint("ShowToast") public IDocumentLayout(Context context, TextPaint textPaint) { paint = textPaint; text = ""; measuredHeight = 0; lineCount = 0; textChange = false; displayMetrics = context.getResources().getDisplayMetrics(); toast = Toast.makeText(context, "", Toast.LENGTH_SHORT); params = new LayoutParams(); params.setLineHeightMultiplier(1.0f); params.setHyphenated(false); params.setReverse(false); } protected void showToast(String s) { toast.setText(s); toast.show(); } public Paint getPaint() { return paint; } public LayoutParams getLayoutParams() { return params; } public CharSequence getText() { return this.text; } public void setText(CharSequence text) { text = text == null ? new SpannableString("") : new SpannableString(text); if (this.text.equals(text)) { return; } this.text = text; this.textChange = true; onTextChange(); } public int getMeasuredHeight() { return measuredHeight; } protected void onTextNull() { params.changed = false; measuredHeight = (int) (params.insetPaddingTop + params.insetPaddingBottom); } public int getLineCount() { return lineCount; } public boolean measure(IProgress<Float> progress, ICancel<Boolean> cancelled) { if (!params.changed && !textChange) { return true; } params.loadToPaint(paint); if (text == null) { text = new SpannableString(""); } else if (!(text instanceof Spannable)) { text = new SpannableString(text); } return onMeasure(progress, cancelled); } protected abstract boolean onMeasure(IProgress<Float> progress, ICancel<Boolean> cancelled); public void draw(Canvas canvas, int startTop, int startBottom) { params.loadToPaint(paint); onDraw(canvas, startTop, startBottom); } protected abstract void onDraw(Canvas canvas, int startTop, int startBottom); public abstract float getTokenAscent(int tokenIndex); public abstract float getTokenDescent(int tokenIndex); public abstract int getTokenForVertical(float y, TokenPosition position); public abstract int getLineForToken(int tokenIndex); public abstract int getTokenStart(int tokenIndex); public abstract int getTokenEnd(int tokenIndex); public abstract float getTokenTopAt(int tokenIndex); public abstract CharSequence getTokenTextAt(int index); public abstract boolean isTokenized(); public abstract void onLayoutParamsChange(); public abstract void onTextChange(); public static enum TokenPosition { START_OF_LINE, END_OF_LINE } public static interface IProgress<T> { public void onUpdate(T val); } public static interface ICancel<T> { public T isCancelled(); } public class LayoutParams { /** * All the customizable parameters */ protected IHyphenator hyphenator = null; protected Float insetPaddingLeft = 0.0f; protected Float insetPaddingTop = 0.0f; protected Float insetPaddingBottom = 0.0f; protected Float insetPaddingRight = 0.0f; protected Float parentWidth = 800.0f; protected Float offsetX = 0.0f; protected Float offsetY = 0.0f; protected Boolean debugging = false; protected Float wordSpacingMultiplier = 1.0f; protected Float lineHeightMultiplier = 0.0f; protected Boolean hyphenated = false; protected Boolean reverse = false; protected Boolean subpixelText = false; protected Boolean antialias = false; protected Integer maxLines = Integer.MAX_VALUE; protected String hyphen = "-"; protected TextAlignment textAlignment = TextAlignment.LEFT; protected Boolean textUnderline = false; protected Boolean textStrikeThru = false; protected Boolean textFakeBold = false; protected Typeface textTypeface = Typeface.DEFAULT; protected Float rawTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, displayMetrics); protected Integer textColor = Color.BLACK; protected Integer textLinkColor = Color.parseColor("#ff05c5cf"); /** * If any settings have changed. */ protected boolean changed = false; public Integer getTextLinkColor() { return textLinkColor; } public void setTextLinkColor(Integer textLinkColor) { this.textLinkColor = textLinkColor; } public void loadToPaint(Paint paint) { paint.setTextSize(rawTextSize); paint.setFakeBoldText(textFakeBold); paint.setStrikeThruText(textStrikeThru); paint.setColor(textColor); paint.setTypeface(textTypeface); paint.setUnderlineText(textUnderline); paint.setAntiAlias(antialias); paint.setSubpixelText(subpixelText); } public Float getWordSpacingMultiplier() { return wordSpacingMultiplier; } public void setWordSpacingMultiplier(float wordSpacingMultiplier) { if (this.wordSpacingMultiplier.equals(wordSpacingMultiplier)) { return; } this.wordSpacingMultiplier = wordSpacingMultiplier; invalidate(); } public TextAlignment getTextAlignment() { return textAlignment; } public void setTextAlignment(/*@NotNull*/ TextAlignment textAlignment) { if (this.textAlignment == textAlignment) { return; } this.textAlignment = textAlignment; invalidate(); } public IHyphenator getHyphenator() { return hyphenator; } public void setHyphenator(IHyphenator hyphenator) { if (hyphenator == null) { return; } if (this.hyphenator != null && this.hyphenator.equals(hyphenator)) { return; } this.hyphenator = hyphenator; invalidate(); } public float getInsetPaddingLeft() { return insetPaddingLeft; } public void setInsetPaddingLeft(float insetPaddingLeft) { if (this.insetPaddingLeft.equals(insetPaddingLeft)) { return; } this.insetPaddingLeft = insetPaddingLeft; invalidate(); } public float getInsetPaddingTop() { return insetPaddingTop; } public void setInsetPaddingTop(float insetPaddingTop) { if (this.insetPaddingTop.equals(insetPaddingTop)) { return; } this.insetPaddingTop = insetPaddingTop; invalidate(); } public float getInsetPaddingBottom() { return insetPaddingBottom; } public void setInsetPaddingBottom(float insetPaddingBottom) { if (this.insetPaddingBottom.equals(insetPaddingBottom)) { return; } this.insetPaddingBottom = insetPaddingBottom; invalidate(); } public float getInsetPaddingRight() { return insetPaddingRight; } public void setInsetPaddingRight(float insetPaddingRight) { if (this.insetPaddingRight.equals(insetPaddingRight)) { return; } this.insetPaddingRight = insetPaddingRight; invalidate(); } public float getParentWidth() { return parentWidth; } public void setParentWidth(float parentWidth) { if (this.parentWidth.equals(parentWidth)) { return; } this.parentWidth = parentWidth; invalidate(); } public float getOffsetX() { return offsetX; } public void setOffsetX(float offsetX) { this.offsetX = offsetX; } public float getOffsetY() { return offsetY; } public void setOffsetY(float offsetY) { this.offsetY = offsetY; } public float getLineHeightMultiplier() { return lineHeightMultiplier; } public void setLineHeightMultiplier(float lineHeightMultiplier) { if (this.lineHeightMultiplier.equals(lineHeightMultiplier)) { return; } this.lineHeightMultiplier = lineHeightMultiplier; invalidate(); } public boolean isHyphenated() { return hyphenated; } public void setHyphenated(boolean hyphenated) { if (this.hyphenated.equals(hyphenated)) { return; } this.hyphenated = hyphenated && hyphenator != null; invalidate(); } public boolean isReverse() { return reverse; } public void setReverse(boolean reverse) { if (this.reverse.equals(reverse)) { return; } this.reverse = reverse; invalidate(); } public int getMaxLines() { return maxLines; } public void setMaxLines(int maxLines) { if (this.maxLines.equals(maxLines)) { return; } this.maxLines = maxLines; invalidate(); } public String getHyphen() { return hyphen; } public void setHyphen(/*@NotNull*/ String hyphen) { if (this.hyphen.equals(hyphen)) { return; } this.hyphen = hyphen; invalidate(); } public boolean hasChanged() { return this.changed; } public void invalidate() { this.changed = true; onLayoutParamsChange(); } public boolean isTextUnderline() { return textUnderline; } public void setTextUnderline(boolean underline) { if (this.textUnderline.equals(underline)) { return; } this.textUnderline = underline; onLayoutParamsChange(); } public boolean isTextStrikeThru() { return textStrikeThru; } public void setTextStrikeThru(boolean strikeThru) { if (this.textStrikeThru.equals(strikeThru)) { return; } this.textStrikeThru = strikeThru; onLayoutParamsChange(); } public boolean isTextFakeBold() { return textFakeBold; } public void setTextFakeBold(boolean fakeBold) { if (this.textFakeBold.equals(fakeBold)) { return; } this.textFakeBold = fakeBold; invalidate(); } public Typeface getTextTypeface() { return textTypeface; } public void setTextTypeface(Typeface typeface) { if (this.textTypeface.equals(typeface)) { return; } this.textTypeface = typeface; invalidate(); } public void setTextSize(int unit, float size) { setRawTextSize(TypedValue.applyDimension(unit, size, displayMetrics)); } public float getTextSize() { return rawTextSize; } public void setTextSize(float size) { setTextSize(TypedValue.COMPLEX_UNIT_SP, size); } public void setRawTextSize(float textSize) { if (this.rawTextSize.equals(textSize)) { return; } this.rawTextSize = textSize; invalidate(); } public int getTextColor() { return textColor; } public void setTextColor(int textColor) { if (this.textColor.equals(textColor)) { return; } this.textColor = textColor; onLayoutParamsChange(); } public boolean isDebugging() { return debugging; } public void setDebugging(Boolean debugging) { if (this.debugging.equals(debugging)) { return; } this.debugging = debugging; onLayoutParamsChange(); } public boolean isTextSubPixel() { return subpixelText; } public void setTextSubPixel(boolean subpixelText) { if (this.subpixelText.equals(subpixelText)) { return; } this.subpixelText = subpixelText; } public boolean isAntiAlias() { return antialias; } public void setAntialias(boolean antialias) { if (this.antialias.equals(antialias)) { return; } this.antialias = antialias; } } }