/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.policy;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
import com.android.internal.R;
/**
* This widget display an analogic clock with two hands for hours and
* minutes.
*/
public class Clock extends TextView {
protected boolean mAttached;
protected Calendar mCalendar;
protected String mClockFormatString;
protected SimpleDateFormat mClockFormat;
public static final int AM_PM_STYLE_NORMAL = 0;
public static final int AM_PM_STYLE_SMALL = 1;
public static final int AM_PM_STYLE_GONE = 2;
public static final int PROTEKK_O_CLOCK = 3;
protected int mAmPmStyle = AM_PM_STYLE_GONE;
public static final int WEEKDAY_STYLE_GONE = 0;
public static final int WEEKDAY_STYLE_SMALL = 1;
public static final int WEEKDAY_STYLE_NORMAL = 2;
protected int mWeekdayStyle = WEEKDAY_STYLE_GONE;
public static final int STYLE_HIDE_CLOCK = 0;
public static final int STYLE_CLOCK_RIGHT = 1;
public static final int STYLE_CLOCK_CENTER = 2;
protected int mClockStyle = STYLE_CLOCK_RIGHT;
protected int mClockColor = com.android.internal.R.color.holo_blue_light;
public Clock(Context context) {
this(context, null);
}
public Clock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Clock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = Calendar.getInstance(TimeZone.getDefault());
// Make sure we update to the current time
//no need to updateClock here, since we call updateSettings() which has updateClock();
//updateClock();
SettingsObserver settingsObserver = new SettingsObserver(new Handler());
settingsObserver.observe();
updateSettings();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
}
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
if (mClockFormat != null) {
mClockFormat.setTimeZone(mCalendar.getTimeZone());
}
}
updateClock();
}
};
final void updateClock() {
mCalendar.setTimeInMillis(System.currentTimeMillis());
if (mAmPmStyle == PROTEKK_O_CLOCK) {
setText("99:99");
} else {
setText(getSmallTime());
}
}
private final CharSequence getSmallTime() {
Context context = getContext();
boolean b24 = DateFormat.is24HourFormat(context);
int res;
if (b24) {
res = R.string.twenty_four_hour_time_format;
} else {
res = R.string.twelve_hour_time_format;
}
final char MAGIC1 = '\uEF00';
final char MAGIC2 = '\uEF01';
SimpleDateFormat sdf;
String format = context.getString(res);
if (!format.equals(mClockFormatString)) {
mClockFormat = sdf = new SimpleDateFormat(format);
mClockFormatString = format;
} else {
sdf = mClockFormat;
}
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
String todayIs = null;
String result = sdf.format(mCalendar.getTime());
if (mWeekdayStyle != WEEKDAY_STYLE_GONE) {
todayIs = whatDay(day);
result = todayIs + result;
}
SpannableStringBuilder formatted = new SpannableStringBuilder(result);
if (!b24) {
if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
String AmPm;
if (format.indexOf("a")==0) {
AmPm = (new SimpleDateFormat("a ")).format(mCalendar.getTime());
} else {
AmPm = (new SimpleDateFormat(" a")).format(mCalendar.getTime());
}
if (mAmPmStyle == AM_PM_STYLE_GONE) {
formatted.delete(result.indexOf(AmPm), result.lastIndexOf(AmPm)+AmPm.length());
} else {
if (mAmPmStyle == AM_PM_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, result.indexOf(AmPm), result.lastIndexOf(AmPm)+AmPm.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
}
}
if (mWeekdayStyle != WEEKDAY_STYLE_NORMAL) {
if (todayIs != null) {
if (mWeekdayStyle == WEEKDAY_STYLE_GONE) {
formatted.delete(result.indexOf(todayIs), result.lastIndexOf(todayIs)+todayIs.length());
} else {
if (mWeekdayStyle == WEEKDAY_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, result.indexOf(todayIs), result.lastIndexOf(todayIs)+todayIs.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
}
}
return formatted;
}
/**
* pull the int given by DAY_OF_WEEK into a day string
*/
private String whatDay(int today) {
String todayIs = null;
switch (today) {
case 1:
todayIs = getResources().getString(R.string.day_of_week_medium_sunday);
break;
case 2:
todayIs = getResources().getString(R.string.day_of_week_medium_monday);
break;
case 3:
todayIs = getResources().getString(R.string.day_of_week_medium_tuesday);
break;
case 4:
todayIs = getResources().getString(R.string.day_of_week_medium_wednesday);
break;
case 5:
todayIs = getResources().getString(R.string.day_of_week_medium_thursday);
break;
case 6:
todayIs = getResources().getString(R.string.day_of_week_medium_friday);
break;
case 7:
todayIs = getResources().getString(R.string.day_of_week_medium_saturday);
break;
}
return todayIs.toUpperCase() + " ";
}
protected class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
super(handler);
}
void observe() {
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.System
.getUriFor(Settings.System.STATUSBAR_CLOCK_AM_PM_STYLE),
false, this);
resolver.registerContentObserver(Settings.System
.getUriFor(Settings.System.STATUSBAR_CLOCK_STYLE), false,
this);
resolver.registerContentObserver(Settings.System
.getUriFor(Settings.System.STATUSBAR_CLOCK_COLOR), false,
this);
resolver.registerContentObserver(Settings.System
.getUriFor(Settings.System.STATUSBAR_CLOCK_WEEKDAY), false,
this);
updateSettings();
}
@Override
public void onChange(boolean selfChange) {
updateSettings();
}
}
protected void updateSettings() {
ContentResolver resolver = mContext.getContentResolver();
int defaultColor = getResources().getColor(
com.android.internal.R.color.holo_blue_light);
mAmPmStyle = Settings.System.getInt(resolver,
Settings.System.STATUSBAR_CLOCK_AM_PM_STYLE, AM_PM_STYLE_GONE);
mClockStyle = Settings.System.getInt(resolver,
Settings.System.STATUSBAR_CLOCK_STYLE, STYLE_CLOCK_RIGHT);
mWeekdayStyle = Settings.System.getInt(resolver,
Settings.System.STATUSBAR_CLOCK_WEEKDAY, WEEKDAY_STYLE_GONE);
mClockColor = Settings.System.getInt(resolver,
Settings.System.STATUSBAR_CLOCK_COLOR, defaultColor);
if (mClockColor == Integer.MIN_VALUE) {
// flag to reset the color
mClockColor = defaultColor;
}
setTextColor(mClockColor);
updateClockVisibility();
updateClock();
}
protected void updateClockVisibility() {
if (mClockStyle == STYLE_CLOCK_RIGHT)
setVisibility(View.VISIBLE);
else
setVisibility(View.GONE);
}
}