Home | History | Annotate | Download | only in time
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.datetimepicker.time;
     18 
     19 import android.content.Context;
     20 import android.content.res.Resources;
     21 import android.graphics.Canvas;
     22 import android.graphics.Paint;
     23 import android.graphics.Typeface;
     24 import android.graphics.Paint.Align;
     25 import android.util.Log;
     26 import android.view.View;
     27 
     28 import com.android.datetimepicker.R;
     29 import com.android.datetimepicker.Utils;
     30 
     31 import java.text.DateFormatSymbols;
     32 
     33 /**
     34  * Draw the two smaller AM and PM circles next to where the larger circle will be.
     35  */
     36 class AmPmCirclesView extends View {
     37     private static final String TAG = "AmPmCirclesView";
     38 
     39     // Alpha level for selected circle.
     40     private static final int SELECTED_ALPHA = Utils.SELECTED_ALPHA;
     41     private static final int SELECTED_ALPHA_THEME_DARK = Utils.SELECTED_ALPHA_THEME_DARK;
     42 
     43     private final Paint mPaint = new Paint();
     44     private int mSelectedAlpha;
     45     private int mUnselectedColor;
     46     private int mAmPmTextColor;
     47     private int mSelectedColor;
     48     private float mCircleRadiusMultiplier;
     49     private float mAmPmCircleRadiusMultiplier;
     50     private String mAmText;
     51     private String mPmText;
     52     private boolean mIsInitialized;
     53 
     54     private static final int AM = TimePickerDialog.AM;
     55     private static final int PM = TimePickerDialog.PM;
     56 
     57     private boolean mDrawValuesReady;
     58     private int mAmPmCircleRadius;
     59     private int mAmXCenter;
     60     private int mPmXCenter;
     61     private int mAmPmYCenter;
     62     private int mAmOrPm;
     63     private int mAmOrPmPressed;
     64 
     65     public AmPmCirclesView(Context context) {
     66         super(context);
     67         mIsInitialized = false;
     68     }
     69 
     70     public void initialize(Context context, int amOrPm) {
     71         if (mIsInitialized) {
     72             Log.e(TAG, "AmPmCirclesView may only be initialized once.");
     73             return;
     74         }
     75 
     76         Resources res = context.getResources();
     77         mUnselectedColor = res.getColor(android.R.color.white);
     78         mSelectedColor = res.getColor(R.color.blue);
     79         mAmPmTextColor = res.getColor(R.color.ampm_text_color);
     80         mSelectedAlpha = SELECTED_ALPHA;
     81         String typefaceFamily = res.getString(R.string.sans_serif);
     82         Typeface tf = Typeface.create(typefaceFamily, Typeface.NORMAL);
     83         mPaint.setTypeface(tf);
     84         mPaint.setAntiAlias(true);
     85         mPaint.setTextAlign(Align.CENTER);
     86 
     87         mCircleRadiusMultiplier =
     88                 Float.parseFloat(res.getString(R.string.circle_radius_multiplier));
     89         mAmPmCircleRadiusMultiplier =
     90                 Float.parseFloat(res.getString(R.string.ampm_circle_radius_multiplier));
     91         String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
     92         mAmText = amPmTexts[0];
     93         mPmText = amPmTexts[1];
     94 
     95         setAmOrPm(amOrPm);
     96         mAmOrPmPressed = -1;
     97 
     98         mIsInitialized = true;
     99     }
    100 
    101     /* package */ void setTheme(Context context, boolean themeDark) {
    102         Resources res = context.getResources();
    103         if (themeDark) {
    104             mUnselectedColor = res.getColor(R.color.dark_gray);
    105             mSelectedColor = res.getColor(R.color.red);
    106             mAmPmTextColor = res.getColor(android.R.color.white);
    107             mSelectedAlpha = SELECTED_ALPHA_THEME_DARK;
    108         } else {
    109             mUnselectedColor = res.getColor(android.R.color.white);
    110             mSelectedColor = res.getColor(R.color.blue);
    111             mAmPmTextColor = res.getColor(R.color.ampm_text_color);
    112             mSelectedAlpha = SELECTED_ALPHA;
    113         }
    114     }
    115 
    116     public void setAmOrPm(int amOrPm) {
    117         mAmOrPm = amOrPm;
    118     }
    119 
    120     public void setAmOrPmPressed(int amOrPmPressed) {
    121         mAmOrPmPressed = amOrPmPressed;
    122     }
    123 
    124     /**
    125      * Calculate whether the coordinates are touching the AM or PM circle.
    126      */
    127     public int getIsTouchingAmOrPm(float xCoord, float yCoord) {
    128         if (!mDrawValuesReady) {
    129             return -1;
    130         }
    131 
    132         int squaredYDistance = (int) ((yCoord - mAmPmYCenter)*(yCoord - mAmPmYCenter));
    133 
    134         int distanceToAmCenter =
    135                 (int) Math.sqrt((xCoord - mAmXCenter)*(xCoord - mAmXCenter) + squaredYDistance);
    136         if (distanceToAmCenter <= mAmPmCircleRadius) {
    137             return AM;
    138         }
    139 
    140         int distanceToPmCenter =
    141                 (int) Math.sqrt((xCoord - mPmXCenter)*(xCoord - mPmXCenter) + squaredYDistance);
    142         if (distanceToPmCenter <= mAmPmCircleRadius) {
    143             return PM;
    144         }
    145 
    146         // Neither was close enough.
    147         return -1;
    148     }
    149 
    150     @Override
    151     public void onDraw(Canvas canvas) {
    152         int viewWidth = getWidth();
    153         if (viewWidth == 0 || !mIsInitialized) {
    154             return;
    155         }
    156 
    157         if (!mDrawValuesReady) {
    158             int layoutXCenter = getWidth() / 2;
    159             int layoutYCenter = getHeight() / 2;
    160             int circleRadius =
    161                     (int) (Math.min(layoutXCenter, layoutYCenter) * mCircleRadiusMultiplier);
    162             mAmPmCircleRadius = (int) (circleRadius * mAmPmCircleRadiusMultiplier);
    163             int textSize = mAmPmCircleRadius * 3 / 4;
    164             mPaint.setTextSize(textSize);
    165 
    166             // Line up the vertical center of the AM/PM circles with the bottom of the main circle.
    167             mAmPmYCenter = layoutYCenter - mAmPmCircleRadius / 2 + circleRadius;
    168             // Line up the horizontal edges of the AM/PM circles with the horizontal edges
    169             // of the main circle.
    170             mAmXCenter = layoutXCenter - circleRadius + mAmPmCircleRadius;
    171             mPmXCenter = layoutXCenter + circleRadius - mAmPmCircleRadius;
    172 
    173             mDrawValuesReady = true;
    174         }
    175 
    176         // We'll need to draw either a lighter blue (for selection), a darker blue (for touching)
    177         // or white (for not selected).
    178         int amColor = mUnselectedColor;
    179         int amAlpha = 255;
    180         int pmColor = mUnselectedColor;
    181         int pmAlpha = 255;
    182         if (mAmOrPm == AM) {
    183             amColor = mSelectedColor;
    184             amAlpha = mSelectedAlpha;
    185         } else if (mAmOrPm == PM) {
    186             pmColor = mSelectedColor;
    187             pmAlpha = mSelectedAlpha;
    188         }
    189         if (mAmOrPmPressed == AM) {
    190             amColor = mSelectedColor;
    191             amAlpha = mSelectedAlpha;
    192         } else if (mAmOrPmPressed == PM) {
    193             pmColor = mSelectedColor;
    194             pmAlpha = mSelectedAlpha;
    195         }
    196 
    197         // Draw the two circles.
    198         mPaint.setColor(amColor);
    199         mPaint.setAlpha(amAlpha);
    200         canvas.drawCircle(mAmXCenter, mAmPmYCenter, mAmPmCircleRadius, mPaint);
    201         mPaint.setColor(pmColor);
    202         mPaint.setAlpha(pmAlpha);
    203         canvas.drawCircle(mPmXCenter, mAmPmYCenter, mAmPmCircleRadius, mPaint);
    204 
    205         // Draw the AM/PM texts on top.
    206         mPaint.setColor(mAmPmTextColor);
    207         int textYCenter = mAmPmYCenter - (int) (mPaint.descent() + mPaint.ascent()) / 2;
    208         canvas.drawText(mAmText, mAmXCenter, textYCenter, mPaint);
    209         canvas.drawText(mPmText, mPmXCenter, textYCenter, mPaint);
    210     }
    211 }
    212