Home | History | Annotate | Download | only in deskclock
      1 /*
      2  * Copyright (C) 2008 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.deskclock;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.database.ContentObserver;
     24 import android.graphics.Typeface;
     25 import android.os.Handler;
     26 import android.provider.Settings;
     27 import android.text.format.DateFormat;
     28 import android.util.AttributeSet;
     29 import android.view.View;
     30 import android.widget.LinearLayout;
     31 import android.widget.TextView;
     32 
     33 import java.text.DateFormatSymbols;
     34 import java.util.Calendar;
     35 import java.util.TimeZone;
     36 
     37 /**
     38  * Displays the time
     39  */
     40 public class DigitalClock extends LinearLayout {
     41 
     42     private final static String HOURS_24 = "kk";
     43     private final static String HOURS = "h";
     44     private final static String MINUTES = ":mm";
     45 
     46     private Calendar mCalendar;
     47     private String mHoursFormat;
     48     private TextView mTimeDisplayHours, mTimeDisplayMinutes;
     49     private AmPm mAmPm;
     50     private ContentObserver mFormatChangeObserver;
     51     private boolean mLive = true;
     52     private boolean mAttached;
     53     private final Typeface mRobotoThin;
     54     private String mTimeZoneId;
     55 
     56 
     57     /* called by system on minute ticks */
     58     private final Handler mHandler = new Handler();
     59     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
     60             @Override
     61             public void onReceive(Context context, Intent intent) {
     62                 if (mLive && intent.getAction().equals(
     63                             Intent.ACTION_TIMEZONE_CHANGED)) {
     64                     mCalendar = Calendar.getInstance();
     65                 }
     66                 // Post a runnable to avoid blocking the broadcast.
     67                 mHandler.post(new Runnable() {
     68                         public void run() {
     69                             updateTime();
     70                         }
     71                 });
     72             }
     73         };
     74 
     75     static class AmPm {
     76         private final TextView mAmPm;
     77         private final String mAmString, mPmString;
     78 
     79         AmPm(View parent) {
     80             mAmPm = (TextView) parent.findViewById(R.id.am_pm);
     81 
     82             String[] ampm = new DateFormatSymbols().getAmPmStrings();
     83             mAmString = ampm[0];
     84             mPmString = ampm[1];
     85         }
     86 
     87         void setShowAmPm(boolean show) {
     88             mAmPm.setVisibility(show ? View.VISIBLE : View.GONE);
     89         }
     90 
     91         void setIsMorning(boolean isMorning) {
     92             mAmPm.setText(isMorning ? mAmString : mPmString);
     93         }
     94 
     95         CharSequence getAmPmText() {
     96             return mAmPm.getText();
     97         }
     98     }
     99 
    100     private class FormatChangeObserver extends ContentObserver {
    101         public FormatChangeObserver() {
    102             super(new Handler());
    103         }
    104         @Override
    105         public void onChange(boolean selfChange) {
    106             setDateFormat();
    107             updateTime();
    108         }
    109     }
    110 
    111     public DigitalClock(Context context) {
    112         this(context, null);
    113     }
    114 
    115     public DigitalClock(Context context, AttributeSet attrs) {
    116         super(context, attrs);
    117         mRobotoThin = Typeface.createFromAsset(context.getAssets(),"fonts/Roboto-Thin.ttf");
    118     }
    119 
    120     @Override
    121     protected void onFinishInflate() {
    122         super.onFinishInflate();
    123 
    124         mTimeDisplayHours = (TextView)findViewById(R.id.timeDisplayHours);
    125         mTimeDisplayMinutes = (TextView)findViewById(R.id.timeDisplayMinutes);
    126         mTimeDisplayMinutes.setTypeface(mRobotoThin);
    127         mAmPm = new AmPm(this);
    128         mCalendar = Calendar.getInstance();
    129 
    130         setDateFormat();
    131     }
    132 
    133     @Override
    134     protected void onAttachedToWindow() {
    135         super.onAttachedToWindow();
    136 
    137         if (Log.LOGV) Log.v("onAttachedToWindow " + this);
    138 
    139         if (mAttached) return;
    140         mAttached = true;
    141 
    142         if (mLive) {
    143             /* monitor time ticks, time changed, timezone */
    144             IntentFilter filter = new IntentFilter();
    145             filter.addAction(Intent.ACTION_TIME_TICK);
    146             filter.addAction(Intent.ACTION_TIME_CHANGED);
    147             filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    148             getContext().registerReceiver(mIntentReceiver, filter);
    149         }
    150 
    151         /* monitor 12/24-hour display preference */
    152         mFormatChangeObserver = new FormatChangeObserver();
    153         getContext().getContentResolver().registerContentObserver(
    154                 Settings.System.CONTENT_URI, true, mFormatChangeObserver);
    155 
    156         updateTime();
    157     }
    158 
    159     @Override
    160     protected void onDetachedFromWindow() {
    161         super.onDetachedFromWindow();
    162 
    163         if (!mAttached) return;
    164         mAttached = false;
    165 
    166         if (mLive) {
    167             getContext().unregisterReceiver(mIntentReceiver);
    168         }
    169         getContext().getContentResolver().unregisterContentObserver(
    170                 mFormatChangeObserver);
    171     }
    172 
    173 
    174     void updateTime(Calendar c) {
    175         mCalendar = c;
    176         updateTime();
    177     }
    178 
    179     public void updateTime(int hour, int minute) {
    180         // set the alarm text
    181         final Calendar c = Calendar.getInstance();
    182         c.set(Calendar.HOUR_OF_DAY, hour);
    183         c.set(Calendar.MINUTE, minute);
    184         mCalendar = c;
    185         updateTime();
    186     }
    187 
    188     private void updateTime() {
    189         if (mLive) {
    190             mCalendar.setTimeInMillis(System.currentTimeMillis());
    191         }
    192         if (mTimeZoneId != null) {
    193             mCalendar.setTimeZone(TimeZone.getTimeZone(mTimeZoneId));
    194         }
    195 
    196         StringBuilder fullTimeStr = new StringBuilder();
    197         CharSequence newTime = DateFormat.format(mHoursFormat, mCalendar);
    198         mTimeDisplayHours.setText(newTime);
    199         fullTimeStr.append(newTime);
    200         newTime = DateFormat.format(MINUTES, mCalendar);
    201         fullTimeStr.append(newTime);
    202         mTimeDisplayMinutes.setText(newTime);
    203 
    204         boolean isMorning = mCalendar.get(Calendar.AM_PM) == 0;
    205         mAmPm.setIsMorning(isMorning);
    206         if (!Alarms.get24HourMode(getContext())) {
    207             fullTimeStr.append(mAmPm.getAmPmText());
    208         }
    209 
    210         // Update accessibility string.
    211         setContentDescription(fullTimeStr);
    212     }
    213 
    214     private void setDateFormat() {
    215         mHoursFormat = Alarms.get24HourMode(getContext()) ? HOURS_24 : HOURS;
    216         mAmPm.setShowAmPm(!Alarms.get24HourMode(getContext()));
    217     }
    218 
    219     void setLive(boolean live) {
    220         mLive = live;
    221     }
    222 
    223     public void setTimeZone(String id) {
    224         mTimeZoneId = id;
    225         updateTime();
    226     }
    227 }
    228