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