1/*
2 * Copyright (C) 2014 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
17package com.android.systemui.statusbar.policy;
18
19import android.app.ActivityManager;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.os.UserHandle;
25import android.text.format.DateFormat;
26import android.util.AttributeSet;
27import android.widget.LinearLayout;
28import android.widget.TextClock;
29
30import com.android.systemui.R;
31
32/**
33 * Container for a clock which has two separate views for the clock itself and AM/PM indicator. This
34 * is used to scale the clock independently of AM/PM.
35 */
36public class SplitClockView extends LinearLayout {
37
38    private TextClock mTimeView;
39    private TextClock mAmPmView;
40
41    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
42        @Override
43        public void onReceive(Context context, Intent intent) {
44            final String action = intent.getAction();
45            if (Intent.ACTION_TIME_CHANGED.equals(action)
46                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
47                    || Intent.ACTION_LOCALE_CHANGED.equals(action)
48                    || Intent.ACTION_CONFIGURATION_CHANGED.equals(action)
49                    || Intent.ACTION_USER_SWITCHED.equals(action)) {
50                updatePatterns();
51            }
52        }
53    };
54
55    public SplitClockView(Context context, AttributeSet attrs) {
56        super(context, attrs);
57    }
58
59    @Override
60    protected void onFinishInflate() {
61        super.onFinishInflate();
62        mTimeView = (TextClock) findViewById(R.id.time_view);
63        mAmPmView = (TextClock) findViewById(R.id.am_pm_view);
64        mTimeView.setShowCurrentUserTime(true);
65        mAmPmView.setShowCurrentUserTime(true);
66    }
67
68    @Override
69    protected void onAttachedToWindow() {
70        super.onAttachedToWindow();
71
72        IntentFilter filter = new IntentFilter();
73        filter.addAction(Intent.ACTION_TIME_CHANGED);
74        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
75        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
76        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
77        filter.addAction(Intent.ACTION_USER_SWITCHED);
78        getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null);
79
80        updatePatterns();
81    }
82
83    @Override
84    protected void onDetachedFromWindow() {
85        super.onDetachedFromWindow();
86        getContext().unregisterReceiver(mIntentReceiver);
87    }
88
89    private void updatePatterns() {
90        String formatString = DateFormat.getTimeFormatString(getContext(),
91                ActivityManager.getCurrentUser());
92        int index = getAmPmPartEndIndex(formatString);
93        String timeString;
94        String amPmString;
95        if (index == -1) {
96            timeString = formatString;
97            amPmString = "";
98        } else {
99            timeString = formatString.substring(0, index);
100            amPmString = formatString.substring(index);
101        }
102        mTimeView.setFormat12Hour(timeString);
103        mTimeView.setFormat24Hour(timeString);
104        mTimeView.setContentDescriptionFormat12Hour(formatString);
105        mTimeView.setContentDescriptionFormat24Hour(formatString);
106        mAmPmView.setFormat12Hour(amPmString);
107        mAmPmView.setFormat24Hour(amPmString);
108    }
109
110    /**
111     * @return the index where the AM/PM part starts at the end in {@code formatString} including
112     *         leading white spaces or {@code -1} if no AM/PM part is found or {@code formatString}
113     *         doesn't end with AM/PM part
114     */
115    private static int getAmPmPartEndIndex(String formatString) {
116        boolean hasAmPm = false;
117        int length = formatString.length();
118        for (int i = length - 1; i >= 0; i--) {
119            char c = formatString.charAt(i);
120            boolean isAmPm = c == 'a';
121            boolean isWhitespace = Character.isWhitespace(c);
122            if (isAmPm) {
123                hasAmPm = true;
124            }
125            if (isAmPm || isWhitespace) {
126                continue;
127            }
128            if (i == length - 1) {
129
130                // First character was not AM/PM and not whitespace, so it's not ending with AM/PM.
131                return -1;
132            } else {
133
134                // If we have AM/PM at all, return last index, or -1 to indicate that it's not
135                // ending with AM/PM.
136                return hasAmPm ? i + 1 : -1;
137            }
138        }
139
140        // Only AM/PM and whitespaces? The whole string is AM/PM. Else: Only whitespaces in the
141        // string.
142        return hasAmPm ? 0 : -1;
143    }
144
145}
146