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.content.res.Resources; 24 import android.database.ContentObserver; 25 import android.graphics.Typeface; 26 import android.os.Handler; 27 import android.provider.Settings; 28 import android.text.format.DateFormat; 29 import android.util.AttributeSet; 30 import android.view.View; 31 import android.widget.LinearLayout; 32 import android.widget.TextView; 33 34 import java.text.DateFormatSymbols; 35 import java.util.Calendar; 36 37 /** 38 * Displays the time 39 */ 40 public class DigitalClock extends LinearLayout { 41 42 private final static String M12 = "h:mm"; 43 44 private Calendar mCalendar; 45 private String mFormat; 46 private TextView mTimeDisplay; 47 private AmPm mAmPm; 48 private ContentObserver mFormatChangeObserver; 49 private boolean mLive = true; 50 private boolean mAttached; 51 52 /* called by system on minute ticks */ 53 private final Handler mHandler = new Handler(); 54 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 55 @Override 56 public void onReceive(Context context, Intent intent) { 57 if (mLive && intent.getAction().equals( 58 Intent.ACTION_TIMEZONE_CHANGED)) { 59 mCalendar = Calendar.getInstance(); 60 } 61 // Post a runnable to avoid blocking the broadcast. 62 mHandler.post(new Runnable() { 63 public void run() { 64 updateTime(); 65 } 66 }); 67 } 68 }; 69 70 private static Typeface sTypeface; 71 72 static class AmPm { 73 private TextView mAmPm; 74 private String mAmString, mPmString; 75 AmPm(View parent)76 AmPm(View parent) { 77 mAmPm = (TextView) parent.findViewById(R.id.am_pm); 78 79 String[] ampm = new DateFormatSymbols().getAmPmStrings(); 80 mAmString = ampm[0]; 81 mPmString = ampm[1]; 82 } 83 setShowAmPm(boolean show)84 void setShowAmPm(boolean show) { 85 mAmPm.setVisibility(show ? View.VISIBLE : View.GONE); 86 } 87 setIsMorning(boolean isMorning)88 void setIsMorning(boolean isMorning) { 89 mAmPm.setText(isMorning ? mAmString : mPmString); 90 } 91 } 92 93 private class FormatChangeObserver extends ContentObserver { FormatChangeObserver()94 public FormatChangeObserver() { 95 super(new Handler()); 96 } 97 @Override onChange(boolean selfChange)98 public void onChange(boolean selfChange) { 99 setDateFormat(); 100 updateTime(); 101 } 102 } 103 DigitalClock(Context context)104 public DigitalClock(Context context) { 105 this(context, null); 106 } 107 DigitalClock(Context context, AttributeSet attrs)108 public DigitalClock(Context context, AttributeSet attrs) { 109 super(context, attrs); 110 } 111 112 @Override onFinishInflate()113 protected void onFinishInflate() { 114 super.onFinishInflate(); 115 116 if (sTypeface == null) { 117 sTypeface = Typeface.createFromAsset(getContext().getAssets(), 118 "fonts/Clockopia.ttf"); 119 } 120 mTimeDisplay = (TextView) findViewById(R.id.timeDisplay); 121 mTimeDisplay.setTypeface(sTypeface); 122 mAmPm = new AmPm(this); 123 mCalendar = Calendar.getInstance(); 124 125 setDateFormat(); 126 } 127 128 @Override onAttachedToWindow()129 protected void onAttachedToWindow() { 130 super.onAttachedToWindow(); 131 132 if (Log.LOGV) Log.v("onAttachedToWindow " + this); 133 134 if (mAttached) return; 135 mAttached = true; 136 137 if (mLive) { 138 /* monitor time ticks, time changed, timezone */ 139 IntentFilter filter = new IntentFilter(); 140 filter.addAction(Intent.ACTION_TIME_TICK); 141 filter.addAction(Intent.ACTION_TIME_CHANGED); 142 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 143 getContext().registerReceiver(mIntentReceiver, filter); 144 } 145 146 /* monitor 12/24-hour display preference */ 147 mFormatChangeObserver = new FormatChangeObserver(); 148 getContext().getContentResolver().registerContentObserver( 149 Settings.System.CONTENT_URI, true, mFormatChangeObserver); 150 151 updateTime(); 152 } 153 154 @Override onDetachedFromWindow()155 protected void onDetachedFromWindow() { 156 super.onDetachedFromWindow(); 157 158 if (!mAttached) return; 159 mAttached = false; 160 161 if (mLive) { 162 getContext().unregisterReceiver(mIntentReceiver); 163 } 164 getContext().getContentResolver().unregisterContentObserver( 165 mFormatChangeObserver); 166 } 167 168 updateTime(Calendar c)169 void updateTime(Calendar c) { 170 mCalendar = c; 171 updateTime(); 172 } 173 updateTime()174 private void updateTime() { 175 if (mLive) { 176 mCalendar.setTimeInMillis(System.currentTimeMillis()); 177 } 178 179 CharSequence newTime = DateFormat.format(mFormat, mCalendar); 180 mTimeDisplay.setText(newTime); 181 mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0); 182 } 183 setDateFormat()184 private void setDateFormat() { 185 mFormat = Alarms.get24HourMode(getContext()) ? Alarms.M24 : M12; 186 mAmPm.setShowAmPm(mFormat == M12); 187 } 188 setLive(boolean live)189 void setLive(boolean live) { 190 mLive = live; 191 } 192 setTypeface(Typeface tf)193 void setTypeface(Typeface tf) { 194 mTimeDisplay.setTypeface(tf); 195 } 196 } 197