• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AmPm(View parent)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 
setShowAmPm(boolean show)87         void setShowAmPm(boolean show) {
88             mAmPm.setVisibility(show ? View.VISIBLE : View.GONE);
89         }
90 
setIsMorning(boolean isMorning)91         void setIsMorning(boolean isMorning) {
92             mAmPm.setText(isMorning ? mAmString : mPmString);
93         }
94 
getAmPmText()95         CharSequence getAmPmText() {
96             return mAmPm.getText();
97         }
98     }
99 
100     private class FormatChangeObserver extends ContentObserver {
FormatChangeObserver()101         public FormatChangeObserver() {
102             super(new Handler());
103         }
104         @Override
onChange(boolean selfChange)105         public void onChange(boolean selfChange) {
106             setDateFormat();
107             updateTime();
108         }
109     }
110 
DigitalClock(Context context)111     public DigitalClock(Context context) {
112         this(context, null);
113     }
114 
DigitalClock(Context context, AttributeSet attrs)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
onFinishInflate()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
onAttachedToWindow()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
onDetachedFromWindow()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 
updateTime(Calendar c)174     void updateTime(Calendar c) {
175         mCalendar = c;
176         updateTime();
177     }
178 
updateTime(int hour, int minute)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 
updateTime()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 
setDateFormat()214     private void setDateFormat() {
215         mHoursFormat = Alarms.get24HourMode(getContext()) ? HOURS_24 : HOURS;
216         mAmPm.setShowAmPm(!Alarms.get24HourMode(getContext()));
217     }
218 
setLive(boolean live)219     void setLive(boolean live) {
220         mLive = live;
221     }
222 
setTimeZone(String id)223     public void setTimeZone(String id) {
224         mTimeZoneId = id;
225         updateTime();
226     }
227 }
228