package info.guardianproject.securereaderinterface.widgets;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import info.guardianproject.securereaderinterface.models.ViewPagerIndicator;
import info.guardianproject.securereaderinterface.R;
public class DottedProgressView extends View implements ViewPagerIndicator
{
private Paint mPaint;
private int mGravity;
private int mDistance; // Distance between dots
private int mRadius; // Size of a dot
private int mColor; // Dot color
private int mRimColor; // Dot rim color
private int mColorCurrent; // Dot color
private int mRimColorCurrent; // Dot rim color
private int mNumDots; // Total number of dots
private int mCurrentDot; // Current dot
private boolean mHideIfOnlyOne = true;
public DottedProgressView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(attrs);
}
public DottedProgressView(Context context, AttributeSet attrs)
{
super(context, attrs);
init(attrs);
}
public DottedProgressView(Context context)
{
super(context);
init(null);
}
private void init(AttributeSet attrs)
{
mGravity = Gravity.CENTER;
if (attrs != null)
{
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DottedProgressView);
mGravity = a.getInt(R.styleable.DottedProgressView_android_gravity, Gravity.CENTER);
mDistance = a.getInt(R.styleable.DottedProgressView_dot_distance, 21);
mRadius = a.getInt(R.styleable.DottedProgressView_dot_radius, 5);
mColor = a.getColor(R.styleable.DottedProgressView_dot_color, Color.TRANSPARENT);
mRimColor = a.getColor(R.styleable.DottedProgressView_dot_rim_color, 0xff888888);
mColorCurrent = a.getColor(R.styleable.DottedProgressView_dot_color_current, 0xff888888);
mRimColorCurrent = a.getColor(R.styleable.DottedProgressView_dot_rim_color_current, 0xff888888);
mNumDots = a.getInt(R.styleable.DottedProgressView_dot_total, 3);
mCurrentDot = a.getInt(R.styleable.DottedProgressView_dot_current, 1);
mHideIfOnlyOne = a.getBoolean(R.styleable.DottedProgressView_hide_if_only_one, true);
a.recycle();
}
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mColor);
mPaint.setStrokeWidth(1);
}
/*
* Get the total number of dots for the view.
*/
public int getNumberOfDots()
{
return mNumDots;
};
/*
* Set the total number of dots for the view.
*/
public void setNumberOfDots(int dots)
{
if (dots != mNumDots)
{
mNumDots = dots;
invalidate();
}
}
/*
* Get the current dot index for the view (0-indexed).
*/
public int getCurrentDot()
{
return mCurrentDot;
};
/*
* Set the current dot index for the view (0-indexed).
*/
public void setCurrentDot(int index)
{
if (index != mCurrentDot)
{
mCurrentDot = index;
invalidate();
}
}
/*
* Calculate the number of dots we can fit in the screen space we are given.
*/
private int getMaxNumberOfDots()
{
if (mRadius < 1 || mDistance <= (2 * mRadius))
return 0;
int w = this.getWidth();
w -= 2 * mRadius;
int n = 1 + w / mDistance;
if (n < 1)
return 0;
return n;
}
private int getDotXPosition(int dot, int numToDraw)
{
if (mGravity == Gravity.RIGHT)
{
int x = getWidth() - mDistance;
int widthToDraw = ((numToDraw - 1) * mDistance);
x -= widthToDraw;
x += dot * mDistance;
return x;
}
else
{
int x = getWidth() / 2;
int widthToDraw = ((numToDraw - 1) * mDistance);
x -= widthToDraw / 2;
x += dot * mDistance;
return x;
}
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (mNumDots <= 1 && mHideIfOnlyOne)
{
return;
}
int sc = canvas.save();
int numDotsToDraw = mNumDots;
int currentDot = mCurrentDot;
// If all dots don't fit, show only the remaining pages (see design
// document)
//
int dotsPerPage = getMaxNumberOfDots();
if (dotsPerPage < mNumDots)
{
// Get the current "page" for the current dot
int page = (int) ((float) mCurrentDot / (dotsPerPage - 1));
currentDot = (int) ((float) mCurrentDot % (dotsPerPage - 1));
numDotsToDraw = Math.min(dotsPerPage, 1 + mNumDots - (page * dotsPerPage));
}
// Do the draw
for (int i = 0; i < numDotsToDraw; i++)
{
if (i == currentDot)
{
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mColorCurrent);
canvas.drawCircle(getDotXPosition(i, numDotsToDraw), getHeight() / 2, mRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mRimColorCurrent);
canvas.drawCircle(getDotXPosition(i, numDotsToDraw), getHeight() / 2, mRadius, mPaint);
}
else
{
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mColor);
canvas.drawCircle(getDotXPosition(i, numDotsToDraw), getHeight() / 2, mRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mRimColor);
canvas.drawCircle(getDotXPosition(i, numDotsToDraw), getHeight() / 2, mRadius, mPaint);
}
}
canvas.restoreToCount(sc);
}
@Override
public void onTotalChanged(int total)
{
this.setNumberOfDots(total);
if (mHideIfOnlyOne)
{
if (total <= 1)
setVisibility(View.INVISIBLE);
else
setVisibility(View.VISIBLE);
}
}
@Override
public void onCurrentChanged(int current)
{
this.setCurrentDot(current);
}
}