163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonpackage com.android.deskclock;
263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.content.Context;
47c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelsonimport android.content.SharedPreferences;
563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.content.res.Configuration;
663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.content.res.Resources;
763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.graphics.Canvas;
863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.graphics.Paint;
963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.graphics.RectF;
1063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.util.AttributeSet;
1163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonimport android.view.View;
1263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
13113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzsteinimport com.android.deskclock.stopwatch.Stopwatches;
14113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein
1563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson/**
1663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson * TODO: Insert description here. (generated by isaackatz)
1763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson */
1863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelsonpublic class CircleTimerView extends View {
1963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
2063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
2163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private int mRedColor;
2263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private int mWhiteColor;
2363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private long mIntervalTime = 0;
2463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private long mIntervalStartTime = -1;
2563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private long mMarkerTime = -1;
2663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private long mCurrentIntervalTime = 0;
2763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private long mAccumulatedTime = 0;
2863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private boolean mPaused = false;
29a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas    private boolean mAnimate = false;
30386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein    private static float mCircleXCenterLeftPadding = 0;
3163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private static float mStrokeSize = 4;
32860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson    private static float mDiamondStrokeSize = 12;
33860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson    private static float mMarkerStrokeSize = 2;
3463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private final Paint mPaint = new Paint();
3584f26ac1eba4f3913190e4a48f1d5967cffccb55Robyn Coultas    private final Paint mFill = new Paint();
3663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private final RectF mArcRect = new RectF();
3784f26ac1eba4f3913190e4a48f1d5967cffccb55Robyn Coultas    private float mRectHalfWidth = 6f;
3863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private Resources mResources;
39860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson    private float mRadiusOffset;   // amount to remove from radius to account for markers on circle
4094622b4b354c09b80e809fef868fdd17c43d3aceYorke Lee    private float mScreenDensity;
4163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
4263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    // Class has 2 modes:
4363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    // Timer mode - counting down. in this mode the animation is counter-clockwise and stops at 0
4463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    // Stop watch mode - counting up - in this mode the animation is clockwise and will keep the
4563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    //                   animation until stopped.
4663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private boolean mTimerMode = false; // default is stop watch view
4763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
4863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public CircleTimerView(Context context) {
4963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        this(context, null);
5063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
5163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
5263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public CircleTimerView(Context context, AttributeSet attrs) {
5363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        super(context, attrs);
5463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        init(context);
5563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
5663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
5763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void setIntervalTime(long t) {
5863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mIntervalTime = t;
59a4faa0547d888cb8bc94a903c36c5a1370ca23b2Isaac Katzenelson        postInvalidate();
6063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
6163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
6263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void setMarkerTime(long t) {
63113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        mMarkerTime = t;
64a4faa0547d888cb8bc94a903c36c5a1370ca23b2Isaac Katzenelson        postInvalidate();
6563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
6663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
6763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void reset() {
6863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mIntervalStartTime = -1;
6963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mMarkerTime = -1;
70a4faa0547d888cb8bc94a903c36c5a1370ca23b2Isaac Katzenelson        postInvalidate();
7163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
7263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void startIntervalAnimation() {
73113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        mIntervalStartTime = Utils.getTimeNow();
74a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        mAnimate = true;
75a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        invalidate();
7663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mPaused = false;
7763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
7863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void stopIntervalAnimation() {
79a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        mAnimate = false;
8063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mIntervalStartTime = -1;
8163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mAccumulatedTime = 0;
8263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
8363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
8463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public boolean isAnimating() {
8563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        return (mIntervalStartTime != -1);
8663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
8763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
8863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void pauseIntervalAnimation() {
89a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        mAnimate = false;
90113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        mAccumulatedTime += Utils.getTimeNow() - mIntervalStartTime;
9163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mPaused = true;
9263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
9363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
9422ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas    public void abortIntervalAnimation() {
95a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        mAnimate = false;
9622ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas    }
9722ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas
98644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson    public void setPassedTime(long time, boolean drawRed) {
99644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // The onDraw() method checks if mIntervalStartTime has been set before drawing any red.
100644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // Without drawRed, mIntervalStartTime should not be set here at all, and would remain at -1
101644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // when the state is reconfigured after exiting and re-entering the application.
102644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // If the timer is currently running, this drawRed will not be set, and will have no effect
103644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // because mIntervalStartTime will be set when the thread next runs.
104644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // When the timer is not running, mIntervalStartTime will not be set upon loading the state,
105644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // and no red will be drawn, so drawRed is used to force onDraw() to draw the red portion,
106644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        // despite the timer not running.
107644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        mCurrentIntervalTime = mAccumulatedTime = time;
108644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        if (drawRed) {
109644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson            mIntervalStartTime = Utils.getTimeNow();
110644a5d887d7033e669ac362a8ed6e79197d13c72Itzhak Katzenelson        }
111a4faa0547d888cb8bc94a903c36c5a1370ca23b2Isaac Katzenelson        postInvalidate();
11263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
11363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
11463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
11563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
11663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    private void init(Context c) {
11763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
11863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mResources = c.getResources();
119386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein        mCircleXCenterLeftPadding = (mResources.getDimension(R.dimen.timer_circle_width)
120386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein                - mResources.getDimension(R.dimen.timer_circle_diameter)) / 2;
121860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson        mStrokeSize = mResources.getDimension(R.dimen.circletimer_circle_size);
122860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson        mDiamondStrokeSize = mResources.getDimension(R.dimen.circletimer_diamond_size);
12394622b4b354c09b80e809fef868fdd17c43d3aceYorke Lee        mMarkerStrokeSize = mResources.getDimension(R.dimen.circletimer_marker_size);
124386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein        mRadiusOffset = Utils.calculateRadiusOffset(
125386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein                mStrokeSize, mDiamondStrokeSize, mMarkerStrokeSize);
12663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mPaint.setAntiAlias(true);
12763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mPaint.setStyle(Paint.Style.STROKE);
12863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mWhiteColor = mResources.getColor(R.color.clock_white);
12963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mRedColor = mResources.getColor(R.color.clock_red);
13094622b4b354c09b80e809fef868fdd17c43d3aceYorke Lee        mScreenDensity = mResources.getDisplayMetrics().density;
13184f26ac1eba4f3913190e4a48f1d5967cffccb55Robyn Coultas        mFill.setAntiAlias(true);
13284f26ac1eba4f3913190e4a48f1d5967cffccb55Robyn Coultas        mFill.setStyle(Paint.Style.FILL);
13384f26ac1eba4f3913190e4a48f1d5967cffccb55Robyn Coultas        mFill.setColor(mRedColor);
13484f26ac1eba4f3913190e4a48f1d5967cffccb55Robyn Coultas        mRectHalfWidth = mDiamondStrokeSize / 2f;
13563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
13663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
13763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void setTimerMode(boolean mode) {
13863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mTimerMode = mode;
13963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
14063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
14163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    @Override
14263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    public void onDraw(Canvas canvas) {
14363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        int xCenter = getWidth() / 2 + 1;
14463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        int yCenter = getHeight() / 2;
14563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
14663211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        mPaint.setStrokeWidth(mStrokeSize);
147860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson        float radius = Math.min(xCenter, yCenter) - mRadiusOffset;
14863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
14963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
150860de0e94f5588369985063127512dc2270cd7deItzhak Katzenelson            xCenter = (int) (radius + mRadiusOffset);
151386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein            if (mTimerMode) {
152386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein                xCenter += mCircleXCenterLeftPadding;
153386d8b05069c95899149c4b18542fc18c3761314Sam Blitzstein            }
15463211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson        }
15563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
15685d5bb1d168a496f02d92320319628a452360fb5Yorke Lee        if (mIntervalStartTime == -1) {
15785d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            // just draw a complete white circle, no red arc needed
15885d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            mPaint.setColor(mWhiteColor);
15985d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            canvas.drawCircle (xCenter, yCenter, radius, mPaint);
16022ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas            if (mTimerMode) {
16122ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas                drawRedDiamond(canvas, 0f, xCenter, yCenter, radius);
16222ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas            }
16385d5bb1d168a496f02d92320319628a452360fb5Yorke Lee        } else {
164a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas            if (mAnimate) {
165a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas                mCurrentIntervalTime = Utils.getTimeNow() - mIntervalStartTime + mAccumulatedTime;
166a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas            }
16785d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            //draw a combination of red and white arcs to create a circle
16863211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            mArcRect.top = yCenter - radius;
16963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            mArcRect.bottom = yCenter + radius;
17063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            mArcRect.left =  xCenter - radius;
17163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            mArcRect.right = xCenter + radius;
17285d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            float redPercent = (float)mCurrentIntervalTime / (float)mIntervalTime;
17389f855e3463ee7505302c8ab0f929067b934742bIsaac Katzenelson            // prevent timer from doing more than one full circle
17485d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            redPercent = (redPercent > 1 && mTimerMode) ? 1 : redPercent;
17563211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
17685d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            float whitePercent = 1 - (redPercent > 1 ? 1 : redPercent);
17785d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            // draw red arc here
17885d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            mPaint.setColor(mRedColor);
17963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            if (mTimerMode){
18085d5bb1d168a496f02d92320319628a452360fb5Yorke Lee                canvas.drawArc (mArcRect, 270, - redPercent * 360 , false, mPaint);
18163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            } else {
18285d5bb1d168a496f02d92320319628a452360fb5Yorke Lee                canvas.drawArc (mArcRect, 270, + redPercent * 360 , false, mPaint);
18363211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson            }
18485d5bb1d168a496f02d92320319628a452360fb5Yorke Lee
18585d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            // draw white arc here
18685d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            mPaint.setStrokeWidth(mStrokeSize);
18785d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            mPaint.setColor(mWhiteColor);
18885d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            if (mTimerMode) {
18985d5bb1d168a496f02d92320319628a452360fb5Yorke Lee                canvas.drawArc(mArcRect, 270, + whitePercent * 360, false, mPaint);
19085d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            } else {
19185d5bb1d168a496f02d92320319628a452360fb5Yorke Lee                canvas.drawArc(mArcRect, 270 + (1 - whitePercent) * 360,
19285d5bb1d168a496f02d92320319628a452360fb5Yorke Lee                        whitePercent * 360, false, mPaint);
19385d5bb1d168a496f02d92320319628a452360fb5Yorke Lee            }
19485d5bb1d168a496f02d92320319628a452360fb5Yorke Lee
195dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee            if (mMarkerTime != -1 && radius > 0 && mIntervalTime != 0) {
196dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                mPaint.setStrokeWidth(mMarkerStrokeSize);
197dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                float angle = (float)(mMarkerTime % mIntervalTime) / (float)mIntervalTime * 360;
198dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                // draw 2dips thick marker
199dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                // the formula to draw the marker 1 unit thick is:
200dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                // 180 / (radius * Math.PI)
201dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                // after that we have to scale it by the screen density
202dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                canvas.drawArc (mArcRect, 270 + angle, mScreenDensity *
203dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee                        (float) (360 / (radius * Math.PI)) , false, mPaint);
204dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee            }
20522ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas            drawRedDiamond(canvas, redPercent, xCenter, yCenter, radius);
20622ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        }
207a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        if (mAnimate) {
208a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas            invalidate();
209a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        }
21022ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas   }
21122ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas
21222ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas    protected void drawRedDiamond(
21322ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas            Canvas canvas, float degrees, int xCenter, int yCenter, float radius) {
21422ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        mPaint.setColor(mRedColor);
21522ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        float diamondPercent;
21622ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        if (mTimerMode) {
21722ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas            diamondPercent = 270 - degrees * 360;
21822ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        } else {
21922ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas            diamondPercent = 270 + degrees * 360;
22022ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        }
221dfb79cf24484f328b479598e7e5659dcaee2ebc7Yorke Lee
22222ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        canvas.save();
22322ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        final double diamondRadians = Math.toRadians(diamondPercent);
22422ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        canvas.translate(xCenter + (float) (radius * Math.cos(diamondRadians)),
22522ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas                yCenter + (float) (radius * Math.sin(diamondRadians)));
22622ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        canvas.rotate(diamondPercent + 45f);
22722ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        canvas.drawRect(-mRectHalfWidth, -mRectHalfWidth, mRectHalfWidth, mRectHalfWidth, mFill);
22822ad7c9ea127b06ee0dc0cb809b59bab33afbf42Robyn Coultas        canvas.restore();
22963211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
23063211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
231113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_PAUSED  = "_ctv_paused";
232113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_INTERVAL  = "_ctv_interval";
233113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_INTERVAL_START = "_ctv_interval_start";
234113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_CURRENT_INTERVAL = "_ctv_current_interval";
235113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_ACCUM_TIME = "_ctv_accum_time";
236113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_TIMER_MODE = "_ctv_timer_mode";
237113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public static final String PREF_CTV_MARKER_TIME = "_ctv_marker_time";
2387c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson
2397c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson    // Since this view is used in multiple places, use the key to save different instances
2407c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson    public void writeToSharedPref(SharedPreferences prefs, String key) {
2417c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        SharedPreferences.Editor editor = prefs.edit();
2427c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.putBoolean (key + PREF_CTV_PAUSED, mPaused);
2437c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.putLong (key + PREF_CTV_INTERVAL, mIntervalTime);
2447c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.putLong (key + PREF_CTV_INTERVAL_START, mIntervalStartTime);
2457c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.putLong (key + PREF_CTV_CURRENT_INTERVAL, mCurrentIntervalTime);
2467c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.putLong (key + PREF_CTV_ACCUM_TIME, mAccumulatedTime);
247a4faa0547d888cb8bc94a903c36c5a1370ca23b2Isaac Katzenelson        editor.putLong (key + PREF_CTV_MARKER_TIME, mMarkerTime);
2487c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.putBoolean (key + PREF_CTV_TIMER_MODE, mTimerMode);
2497c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        editor.apply();
2507c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson    }
2517c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson
2527c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson    public void readFromSharedPref(SharedPreferences prefs, String key) {
2537c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        mPaused = prefs.getBoolean(key + PREF_CTV_PAUSED, false);
2547c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        mIntervalTime = prefs.getLong(key + PREF_CTV_INTERVAL, 0);
255d932d220d4e8b45ed215f928cab2ada71e008e73Itzhak Katzenelson        mIntervalStartTime = prefs.getLong(key + PREF_CTV_INTERVAL_START, -1);
2567c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        mCurrentIntervalTime = prefs.getLong(key + PREF_CTV_CURRENT_INTERVAL, 0);
2577c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        mAccumulatedTime = prefs.getLong(key + PREF_CTV_ACCUM_TIME, 0);
258a4faa0547d888cb8bc94a903c36c5a1370ca23b2Isaac Katzenelson        mMarkerTime = prefs.getLong(key + PREF_CTV_MARKER_TIME, -1);
2597c71fbab5ecd558e60edff636a149ff3bf73ec57Isaac Katzenelson        mTimerMode = prefs.getBoolean(key + PREF_CTV_TIMER_MODE, false);
260a9547df82ab6c49bdea429acd3fe5ebf383ffe42Robyn Coultas        mAnimate = (mIntervalStartTime != -1 && !mPaused);
26163211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson    }
26263211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson
263113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    public void clearSharedPref(SharedPreferences prefs, String key) {
264113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        SharedPreferences.Editor editor = prefs.edit();
265113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (Stopwatches.PREF_START_TIME);
266113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (Stopwatches.PREF_ACCUM_TIME);
267113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (Stopwatches.PREF_STATE);
268113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_PAUSED);
269113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_INTERVAL);
270113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_INTERVAL_START);
271113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_CURRENT_INTERVAL);
272113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_ACCUM_TIME);
273113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_MARKER_TIME);
274113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.remove (key + PREF_CTV_TIMER_MODE);
275113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein        editor.apply();
276113e1daddd8cb0e890084aa4b6ea3194d8ad4826Sam Blitzstein    }
27763211efa1565b5dc171938740ba183302d0e46f3Isaac Katzenelson}
278