1 // Copyright 2013 Google Inc. All Rights Reserved.
2 
3 package com.android.deskclock.widget;
4 
5 import android.content.ContentResolver;
6 import android.content.Context;
7 import android.content.res.TypedArray;
8 import android.database.ContentObserver;
9 import android.net.Uri;
10 import android.os.Handler;
11 import android.provider.Settings;
12 import android.text.format.DateFormat;
13 import android.util.AttributeSet;
14 import android.widget.TextView;
15 
16 import com.android.deskclock.R;
17 import com.android.deskclock.Utils;
18 
19 import java.util.Calendar;
20 
21 /**
22  * Based on {@link android.widget.TextClock}, This widget displays a constant time of day using
23  * format specifiers. {@link android.widget.TextClock} Doesn't support a non ticking clock.
24  */
25 public class TextTime extends TextView {
26     public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm a";
27 
28     public static final CharSequence DEFAULT_FORMAT_24_HOUR = "H:mm";
29 
30     private CharSequence mFormat12;
31     private CharSequence mFormat24;
32     private CharSequence mFormat;
33     private String mContentDescriptionFormat;
34 
35     private boolean mAttached;
36 
37     private int mHour;
38     private int mMinute;
39 
40     private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
41         @Override
42         public void onChange(boolean selfChange) {
43             chooseFormat();
44             updateTime();
45         }
46 
47         @Override
48         public void onChange(boolean selfChange, Uri uri) {
49             chooseFormat();
50             updateTime();
51         }
52     };
53 
54     @SuppressWarnings("UnusedDeclaration")
TextTime(Context context)55     public TextTime(Context context) {
56         this(context, null);
57     }
58 
59     @SuppressWarnings("UnusedDeclaration")
TextTime(Context context, AttributeSet attrs)60     public TextTime(Context context, AttributeSet attrs) {
61         this(context, attrs, 0);
62     }
63 
TextTime(Context context, AttributeSet attrs, int defStyle)64     public TextTime(Context context, AttributeSet attrs, int defStyle) {
65         super(context, attrs, defStyle);
66 
67         final TypedArray styledAttributes = context.obtainStyledAttributes(
68                 attrs, R.styleable.TextTime, defStyle, 0);
69         try {
70             mFormat12 = styledAttributes.getText(R.styleable.TextTime_format12Hour);
71             mFormat24 = styledAttributes.getText(R.styleable.TextTime_format24Hour);
72         } finally {
73             styledAttributes.recycle();
74         }
75         chooseFormat();
76     }
77 
78     @SuppressWarnings("UnusedDeclaration")
getFormat12Hour()79     public CharSequence getFormat12Hour() {
80         return mFormat12;
81     }
82 
83     @SuppressWarnings("UnusedDeclaration")
setFormat12Hour(CharSequence format)84     public void setFormat12Hour(CharSequence format) {
85         mFormat12 = format;
86 
87         chooseFormat();
88         updateTime();
89     }
90 
91     @SuppressWarnings("UnusedDeclaration")
getFormat24Hour()92     public CharSequence getFormat24Hour() {
93         return mFormat24;
94     }
95 
96     @SuppressWarnings("UnusedDeclaration")
setFormat24Hour(CharSequence format)97     public void setFormat24Hour(CharSequence format) {
98         mFormat24 = format;
99 
100         chooseFormat();
101         updateTime();
102     }
103 
chooseFormat()104     private void chooseFormat() {
105         final boolean format24Requested = DateFormat.is24HourFormat(getContext());
106         if (format24Requested) {
107             mFormat = mFormat24 == null ? DEFAULT_FORMAT_24_HOUR : mFormat24;
108         } else {
109             mFormat = mFormat12 == null ? DEFAULT_FORMAT_12_HOUR : mFormat12;
110         }
111         mContentDescriptionFormat = mFormat.toString();
112     }
113 
114     @Override
onAttachedToWindow()115     protected void onAttachedToWindow() {
116         super.onAttachedToWindow();
117         if (!mAttached) {
118             mAttached = true;
119             registerObserver();
120             updateTime();
121         }
122     }
123 
124     @Override
onDetachedFromWindow()125     protected void onDetachedFromWindow() {
126         super.onDetachedFromWindow();
127         if (mAttached) {
128             unregisterObserver();
129             mAttached = false;
130         }
131     }
132 
registerObserver()133     private void registerObserver() {
134         final ContentResolver resolver = getContext().getContentResolver();
135         resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
136     }
137 
unregisterObserver()138     private void unregisterObserver() {
139         final ContentResolver resolver = getContext().getContentResolver();
140         resolver.unregisterContentObserver(mFormatChangeObserver);
141     }
142 
setFormat(Context context)143     public void setFormat(Context context) {
144         setFormat12Hour(Utils.get12ModeFormat(context, true /* showAmPm */));
145         setFormat24Hour(Utils.get24ModeFormat());
146     }
147 
setTime(int hour, int minute)148     public void setTime(int hour, int minute) {
149         mHour = hour;
150         mMinute = minute;
151         updateTime();
152     }
153 
updateTime()154     private void updateTime() {
155         final Calendar calendar = Calendar.getInstance();
156         calendar.set(Calendar.HOUR_OF_DAY, mHour);
157         calendar.set(Calendar.MINUTE, mMinute);
158         setText(DateFormat.format(mFormat, calendar));
159         if (mContentDescriptionFormat != null) {
160             setContentDescription(DateFormat.format(mContentDescriptionFormat, calendar));
161         } else {
162             setContentDescription(DateFormat.format(mFormat, calendar));
163         }
164     }
165 }
166