16e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein/*
26e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * Copyright (C) 2013 The Android Open Source Project
36e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein *
46e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * Licensed under the Apache License, Version 2.0 (the "License");
56e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * you may not use this file except in compliance with the License.
66e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * You may obtain a copy of the License at
76e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein *
86e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein *      http://www.apache.org/licenses/LICENSE-2.0
96e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein *
106e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * Unless required by applicable law or agreed to in writing, software
116e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * distributed under the License is distributed on an "AS IS" BASIS,
126e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * See the License for the specific language governing permissions and
146e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein * limitations under the License.
156e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein */
166e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
17b8f95646fc0510eebfeaa27864023d630f34090fSam Blitzsteinpackage com.android.datetimepicker.time;
186e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
196e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.content.Context;
206e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.content.res.Resources;
216e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.graphics.Canvas;
226e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.graphics.Paint;
236e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.graphics.Typeface;
246e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.graphics.Paint.Align;
256e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.util.Log;
266e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport android.view.View;
276e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
286e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinimport com.android.datetimepicker.R;
296e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
30b8f95646fc0510eebfeaa27864023d630f34090fSam Blitzsteinimport java.text.DateFormatSymbols;
31b8f95646fc0510eebfeaa27864023d630f34090fSam Blitzstein
32f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein/**
33f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein * Draw the two smaller AM and PM circles next to where the larger circle will be.
34f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein */
356e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzsteinpublic class AmPmCirclesView extends View {
366e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private static final String TAG = "AmPmCirclesView";
376e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
38d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein    // Alpha level of blue color for selected circle.
39d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein    private static final int SELECTED_ALPHA = 51;
40d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein    // Alpha level of blue color for pressed circle.
41d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein    private static final int PRESSED_ALPHA = 175;
42d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein
436e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private final Paint mPaint = new Paint();
446e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mWhite;
45f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein    private int mAmPmTextColor;
466e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mBlue;
476e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private float mCircleRadiusMultiplier;
486e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private float mAmPmCircleRadiusMultiplier;
496e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private String mAmText;
506e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private String mPmText;
516e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private boolean mIsInitialized;
526e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
536e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private static final int AM = TimePickerDialog.AM;
546e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private static final int PM = TimePickerDialog.PM;
556e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
566e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private boolean mDrawValuesReady;
576e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mAmPmCircleRadius;
586e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mAmXCenter;
596e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mPmXCenter;
606e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mAmPmYCenter;
616e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mAmOrPm;
626e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    private int mAmOrPmPressed;
636e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
646e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    public AmPmCirclesView(Context context) {
656e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        super(context);
666e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mIsInitialized = false;
676e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    }
686e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
696e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    public void initialize(Context context, int amOrPm) {
706e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (mIsInitialized) {
716e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            Log.e(TAG, "AmPmCirclesView may only be initialized once.");
726e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            return;
736e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
746e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
756e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        Resources res = context.getResources();
766e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mWhite = res.getColor(R.color.white);
77f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein        mAmPmTextColor = res.getColor(R.color.ampm_text_color);
786e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mBlue = res.getColor(R.color.blue);
793d5a23b698cb8c59f43914ea2f9bb4fb36575f88Sam Blitzstein        String typefaceFamily = res.getString(R.string.sans_serif);
803d5a23b698cb8c59f43914ea2f9bb4fb36575f88Sam Blitzstein        Typeface tf = Typeface.create(typefaceFamily, Typeface.NORMAL);
816e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setTypeface(tf);
826e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setAntiAlias(true);
836e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setTextAlign(Align.CENTER);
846e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
856e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mCircleRadiusMultiplier =
866e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein                Float.parseFloat(res.getString(R.string.circle_radius_multiplier));
876e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mAmPmCircleRadiusMultiplier =
886e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein                Float.parseFloat(res.getString(R.string.ampm_circle_radius_multiplier));
89b8f95646fc0510eebfeaa27864023d630f34090fSam Blitzstein        String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
90b8f95646fc0510eebfeaa27864023d630f34090fSam Blitzstein        mAmText = amPmTexts[0];
91b8f95646fc0510eebfeaa27864023d630f34090fSam Blitzstein        mPmText = amPmTexts[1];
926e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
936e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        setAmOrPm(amOrPm);
946e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mAmOrPmPressed = -1;
956e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
966e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mIsInitialized = true;
976e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    }
986e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
996e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    public void setAmOrPm(int amOrPm) {
1006e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mAmOrPm = amOrPm;
1016e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    }
1026e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1036e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    public void setAmOrPmPressed(int amOrPmPressed) {
1046e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mAmOrPmPressed = amOrPmPressed;
1056e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    }
1066e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
107f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein    /**
108f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein     * Calculate whether the coordinates are touching the AM or PM circle.
109f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein     */
1106e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    public int getIsTouchingAmOrPm(float xCoord, float yCoord) {
1116e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (!mDrawValuesReady) {
1126e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            return -1;
1136e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1146e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1156e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int squaredYDistance = (int) ((yCoord - mAmPmYCenter)*(yCoord - mAmPmYCenter));
1166e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1176e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int distanceToAmCenter =
1186e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein                (int) Math.sqrt((xCoord - mAmXCenter)*(xCoord - mAmXCenter) + squaredYDistance);
1196e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (distanceToAmCenter <= mAmPmCircleRadius) {
1206e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            return AM;
1216e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1226e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1236e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int distanceToPmCenter =
1246e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein                (int) Math.sqrt((xCoord - mPmXCenter)*(xCoord - mPmXCenter) + squaredYDistance);
1256e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (distanceToPmCenter <= mAmPmCircleRadius) {
1266e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            return PM;
1276e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1286e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1296e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        // Neither was close enough.
1306e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        return -1;
1316e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    }
1326e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1336e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    @Override
1346e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    public void onDraw(Canvas canvas) {
1356e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int viewWidth = getWidth();
1366e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (viewWidth == 0 || !mIsInitialized) {
1376e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            return;
1386e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1396e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1406e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (!mDrawValuesReady) {
1416e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            int layoutXCenter = getWidth() / 2;
1426e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            int layoutYCenter = getHeight() / 2;
1436e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            int circleRadius =
1446e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein                    (int) (Math.min(layoutXCenter, layoutYCenter) * mCircleRadiusMultiplier);
1456e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            mAmPmCircleRadius = (int) (circleRadius * mAmPmCircleRadiusMultiplier);
146d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein            int textSize = mAmPmCircleRadius * 3 / 4;
1476e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            mPaint.setTextSize(textSize);
1486e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1496e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            // Line up the vertical center of the AM/PM circles with the bottom of the main circle.
1506e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            mAmPmYCenter = layoutYCenter - mAmPmCircleRadius / 2 + circleRadius;
1516e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            // Line up the horizontal edges of the AM/PM circles with the horizontal edges
1526e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            // of the main circle.
1536e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            mAmXCenter = layoutXCenter - circleRadius + mAmPmCircleRadius;
1546e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            mPmXCenter = layoutXCenter + circleRadius - mAmPmCircleRadius;
1556e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
1566e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            mDrawValuesReady = true;
1576e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1586e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
159d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein        // We'll need to draw either a lighter blue (for selection), a darker blue (for touching)
160f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein        // or white (for not selected).
1616e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int amColor = mWhite;
1626e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int amAlpha = 255;
1636e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int pmColor = mWhite;
1646e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int pmAlpha = 255;
1656e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (mAmOrPm == AM) {
1666e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            amColor = mBlue;
167d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein            amAlpha = SELECTED_ALPHA;
1686e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        } else if (mAmOrPm == PM) {
1696e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            pmColor = mBlue;
170d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein            pmAlpha = SELECTED_ALPHA;
1716e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1726e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        if (mAmOrPmPressed == AM) {
1736e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            amColor = mBlue;
174d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein            amAlpha = PRESSED_ALPHA;
1756e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        } else if (mAmOrPmPressed == PM) {
1766e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein            pmColor = mBlue;
177d5ec70d18c6379015acd4725b8804ab79f30bfa0Sam Blitzstein            pmAlpha = PRESSED_ALPHA;
1786e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        }
1796e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
180f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein        // Draw the two circles.
1816e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setColor(amColor);
1826e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setAlpha(amAlpha);
1836e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        canvas.drawCircle(mAmXCenter, mAmPmYCenter, mAmPmCircleRadius, mPaint);
1846e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setColor(pmColor);
1856e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        mPaint.setAlpha(pmAlpha);
1866e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        canvas.drawCircle(mPmXCenter, mAmPmYCenter, mAmPmCircleRadius, mPaint);
1876e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein
188f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein        // Draw the AM/PM texts on top.
189f3b38bd61d583d31200c501f5a74392aac510657Sam Blitzstein        mPaint.setColor(mAmPmTextColor);
1906e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        int textYCenter = mAmPmYCenter - (int) (mPaint.descent() + mPaint.ascent()) / 2;
1916e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        canvas.drawText(mAmText, mAmXCenter, textYCenter, mPaint);
1926e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein        canvas.drawText(mPmText, mPmXCenter, textYCenter, mPaint);
1936e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein    }
1946e896f805cac499b777c98755149f07ccd7ba5c3Sam Blitzstein}
195