package com.marshalchen.common.uimodule.showcaseview;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.text.*;
import android.text.style.TextAppearanceSpan;
import com.marshalchen.common.uimodule.R;
/**
* Draws the text as required by the ShowcaseView
*/
class TextDrawer {
private final TextPaint titlePaint;
private final TextPaint textPaint;
private final Context context;
private final ShowcaseAreaCalculator calculator;
private final float padding;
private final float actionBarOffset;
private CharSequence mTitle, mDetails;
private float[] mBestTextPosition = new float[3];
private DynamicLayout mDynamicTitleLayout;
private DynamicLayout mDynamicDetailLayout;
private TextAppearanceSpan mTitleSpan;
private TextAppearanceSpan mDetailSpan;
private boolean hasRecalculated;
public TextDrawer(Resources resources, ShowcaseAreaCalculator calculator, Context context) {
padding = resources.getDimension(R.dimen.showcase_text_padding);
actionBarOffset = resources.getDimension(R.dimen.showcase_action_bar_offset);
this.calculator = calculator;
this.context = context;
titlePaint = new TextPaint();
titlePaint.setAntiAlias(true);
textPaint = new TextPaint();
textPaint.setAntiAlias(true);
}
public void draw(Canvas canvas) {
if (shouldDrawText()) {
float[] textPosition = getBestTextPosition();
if (!TextUtils.isEmpty(mTitle)) {
canvas.save();
if (hasRecalculated) {
mDynamicTitleLayout = new DynamicLayout(mTitle, titlePaint,
(int) textPosition[2], Layout.Alignment.ALIGN_NORMAL,
1.0f, 1.0f, true);
}
if (mDynamicTitleLayout != null) {
canvas.translate(textPosition[0], textPosition[1]);
mDynamicTitleLayout.draw(canvas);
canvas.restore();
}
}
if (!TextUtils.isEmpty(mDetails)) {
canvas.save();
if (hasRecalculated) {
mDynamicDetailLayout = new DynamicLayout(mDetails, textPaint,
(int) textPosition[2],
Layout.Alignment.ALIGN_NORMAL,
1.2f, 1.0f, true);
}
float offsetForTitle = mDynamicTitleLayout != null ? mDynamicTitleLayout.getHeight() :
0;
if (mDynamicDetailLayout != null) {
canvas.translate(textPosition[0], textPosition[1] + offsetForTitle);
mDynamicDetailLayout.draw(canvas);
canvas.restore();
}
}
}
hasRecalculated = false;
}
public void setContentText(CharSequence details) {
if (details != null) {
SpannableString ssbDetail = new SpannableString(details);
ssbDetail.setSpan(mDetailSpan, 0, ssbDetail.length(), 0);
mDetails = ssbDetail;
}
}
public void setContentTitle(CharSequence title) {
if (title != null) {
SpannableString ssbTitle = new SpannableString(title);
ssbTitle.setSpan(mTitleSpan, 0, ssbTitle.length(), 0);
mTitle = ssbTitle;
}
}
/**
* Calculates the best place to position text
* @param canvasW width of the screen
* @param canvasH height of the screen
* @param shouldCentreText
*/
public void calculateTextPosition(int canvasW, int canvasH, ShowcaseView showcaseView, boolean shouldCentreText) {
Rect showcase = showcaseView.hasShowcaseView() ?
calculator.getShowcaseRect() :
new Rect();
int[] areas = new int[4]; //left, top, right, bottom
areas[0] = showcase.left * canvasH;
areas[1] = showcase.top * canvasW;
areas[2] = (canvasW - showcase.right) * canvasH;
areas[3] = (canvasH - showcase.bottom) * canvasW;
int largest = 0;
for(int i = 1; i < areas.length; i++) {
if(areas[i] > areas[largest])
largest = i;
}
// Position text in largest area
switch(largest) {
case 0:
mBestTextPosition[0] = padding;
mBestTextPosition[1] = padding;
mBestTextPosition[2] = showcase.left - 2 * padding;
break;
case 1:
mBestTextPosition[0] = padding;
mBestTextPosition[1] = padding + actionBarOffset;
mBestTextPosition[2] = canvasW - 2 * padding;
break;
case 2:
mBestTextPosition[0] = showcase.right + padding;
mBestTextPosition[1] = padding;
mBestTextPosition[2] = (canvasW - showcase.right) - 2 * padding;
break;
case 3:
mBestTextPosition[0] = padding;
mBestTextPosition[1] = showcase.bottom + padding;
mBestTextPosition[2] = canvasW - 2 * padding;
break;
}
if(shouldCentreText) {
// Center text vertically or horizontally
switch(largest) {
case 0:
case 2:
mBestTextPosition[1] += canvasH / 4;
break;
case 1:
case 3:
mBestTextPosition[2] /= 2;
mBestTextPosition[0] += canvasW / 4;
break;
}
} else {
// As text is not centered add actionbar padding if the text is left or right
switch(largest) {
case 0:
case 2:
mBestTextPosition[1] += actionBarOffset;
break;
}
}
hasRecalculated = true;
}
public void setTitleStyling(int styleId) {
mTitleSpan = new TextAppearanceSpan(this.context, styleId);
setContentTitle(mTitle);
}
public void setDetailStyling(int styleId) {
mDetailSpan = new TextAppearanceSpan(this.context, styleId);
setContentText(mDetails);
}
public CharSequence getContentTitle() {
return mTitle;
}
public CharSequence getContentText() {
return mDetails;
}
public float[] getBestTextPosition() {
return mBestTextPosition;
}
public boolean shouldDrawText() {
return !TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mDetails);
}
}