1// Copyright 2013 Google Inc. All Rights Reserved.
2
3package com.android.deskclock.widget;
4
5import android.content.ContentResolver;
6import android.content.Context;
7import android.content.res.TypedArray;
8import android.database.ContentObserver;
9import android.net.Uri;
10import android.os.Handler;
11import android.provider.Settings;
12import android.text.format.DateFormat;
13import android.util.AttributeSet;
14import android.widget.TextView;
15
16import com.android.deskclock.R;
17import com.android.deskclock.Utils;
18
19import 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 */
25public 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")
55    public TextTime(Context context) {
56        this(context, null);
57    }
58
59    @SuppressWarnings("UnusedDeclaration")
60    public TextTime(Context context, AttributeSet attrs) {
61        this(context, attrs, 0);
62    }
63
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")
79    public CharSequence getFormat12Hour() {
80        return mFormat12;
81    }
82
83    @SuppressWarnings("UnusedDeclaration")
84    public void setFormat12Hour(CharSequence format) {
85        mFormat12 = format;
86
87        chooseFormat();
88        updateTime();
89    }
90
91    @SuppressWarnings("UnusedDeclaration")
92    public CharSequence getFormat24Hour() {
93        return mFormat24;
94    }
95
96    @SuppressWarnings("UnusedDeclaration")
97    public void setFormat24Hour(CharSequence format) {
98        mFormat24 = format;
99
100        chooseFormat();
101        updateTime();
102    }
103
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
115    protected void onAttachedToWindow() {
116        super.onAttachedToWindow();
117        if (!mAttached) {
118            mAttached = true;
119            registerObserver();
120            updateTime();
121        }
122    }
123
124    @Override
125    protected void onDetachedFromWindow() {
126        super.onDetachedFromWindow();
127        if (mAttached) {
128            unregisterObserver();
129            mAttached = false;
130        }
131    }
132
133    private void registerObserver() {
134        final ContentResolver resolver = getContext().getContentResolver();
135        resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
136    }
137
138    private void unregisterObserver() {
139        final ContentResolver resolver = getContext().getContentResolver();
140        resolver.unregisterContentObserver(mFormatChangeObserver);
141    }
142
143    public void setFormat(int amPmFontSize) {
144        setFormat12Hour(Utils.get12ModeFormat(amPmFontSize));
145        setFormat24Hour(Utils.get24ModeFormat());
146    }
147
148    public void setTime(int hour, int minute) {
149        mHour = hour;
150        mMinute = minute;
151        updateTime();
152    }
153
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