michael@0: /* michael@0: * Copyright (C) 2007 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: package org.mozilla.gecko.widget; michael@0: michael@0: import org.mozilla.gecko.R; michael@0: michael@0: import android.content.Context; michael@0: import android.os.Build; michael@0: import android.text.format.DateFormat; michael@0: import android.text.format.DateUtils; michael@0: import android.util.DisplayMetrics; michael@0: import android.util.Log; michael@0: import android.view.Display; michael@0: import android.view.LayoutInflater; michael@0: import android.view.WindowManager; michael@0: import android.view.accessibility.AccessibilityEvent; michael@0: import android.view.inputmethod.InputMethodManager; michael@0: import android.widget.CalendarView; michael@0: import android.widget.EditText; michael@0: import android.widget.FrameLayout; michael@0: import android.widget.LinearLayout; michael@0: import android.widget.NumberPicker; michael@0: michael@0: import java.text.SimpleDateFormat; michael@0: import java.util.Arrays; michael@0: import java.util.Calendar; michael@0: import java.util.Locale; michael@0: michael@0: public class DateTimePicker extends FrameLayout { michael@0: michael@0: private static final boolean DEBUG = true; michael@0: private static final String LOGTAG = "GeckoDateTimePicker"; michael@0: private static final String DATE_FORMAT = "MM/dd/yyyy"; michael@0: private static final int DEFAULT_START_YEAR = 1; michael@0: private static final int DEFAULT_END_YEAR = 9999; michael@0: // Minimal screen width (in inches) for which we can show the calendar; michael@0: private static final int SCREEN_SIZE_THRESHOLD = 5; michael@0: private boolean mYearEnabled = true; michael@0: private boolean mMonthEnabled = true; michael@0: private boolean mWeekEnabled = false; michael@0: private boolean mDayEnabled = true; michael@0: private boolean mHourEnabled = true; michael@0: private boolean mMinuteEnabled = true; michael@0: private boolean mCalendarEnabled = false; michael@0: private boolean mIs12HourMode; michael@0: // Size of the screen in inches; michael@0: private int mScreenWidth; michael@0: private int mScreenHeight; michael@0: private OnValueChangeListener mOnChangeListener; michael@0: private final LinearLayout mPickers; michael@0: private final LinearLayout mDateSpinners; michael@0: private final LinearLayout mTimeSpinners; michael@0: private final LinearLayout mSpinners; michael@0: private final NumberPicker mDaySpinner; michael@0: private final NumberPicker mMonthSpinner; michael@0: private final NumberPicker mWeekSpinner; michael@0: private final NumberPicker mYearSpinner; michael@0: private final NumberPicker mHourSpinner; michael@0: private final NumberPicker mMinuteSpinner; michael@0: private final NumberPicker mAMPMSpinner; michael@0: private final CalendarView mCalendar; michael@0: private final EditText mDaySpinnerInput; michael@0: private final EditText mMonthSpinnerInput; michael@0: private final EditText mWeekSpinnerInput; michael@0: private final EditText mYearSpinnerInput; michael@0: private final EditText mHourSpinnerInput; michael@0: private final EditText mMinuteSpinnerInput; michael@0: private final EditText mAMPMSpinnerInput; michael@0: private Locale mCurrentLocale; michael@0: private String[] mShortMonths; michael@0: private String[] mShortAMPMs; michael@0: private int mNumberOfMonths; michael@0: private Calendar mTempDate; michael@0: private Calendar mMinDate; michael@0: private Calendar mMaxDate; michael@0: private Calendar mCurrentDate; michael@0: private PickersState mState; michael@0: michael@0: public static enum PickersState { DATE, MONTH, WEEK, TIME, DATETIME }; michael@0: michael@0: public class OnValueChangeListener implements NumberPicker.OnValueChangeListener { michael@0: @Override michael@0: public void onValueChange(NumberPicker picker, int oldVal, int newVal) { michael@0: updateInputState(); michael@0: mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis()); michael@0: boolean newBehavior = (Build.VERSION.SDK_INT > 10); michael@0: if (newBehavior) { michael@0: if (DEBUG) Log.d(LOGTAG, "Sdk version > 10, using new behavior"); michael@0: //The native date picker widget on these sdks increment michael@0: //the next field when one field reach the maximum michael@0: if (picker == mDaySpinner && mDayEnabled) { michael@0: int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH); michael@0: int old = mTempDate.get(Calendar.DAY_OF_MONTH); michael@0: setTempDate(Calendar.DAY_OF_MONTH, old, newVal, 1, maxDayOfMonth); michael@0: } else if (picker == mMonthSpinner && mMonthEnabled) { michael@0: int old = mTempDate.get(Calendar.MONTH); michael@0: setTempDate(Calendar.MONTH, old, newVal, Calendar.JANUARY, Calendar.DECEMBER); michael@0: } else if (picker == mWeekSpinner) { michael@0: int old = mTempDate.get(Calendar.WEEK_OF_YEAR); michael@0: int maxWeekOfYear = mTempDate.getActualMaximum(Calendar.WEEK_OF_YEAR); michael@0: setTempDate(Calendar.WEEK_OF_YEAR, old, newVal, 0, maxWeekOfYear); michael@0: } else if (picker == mYearSpinner && mYearEnabled) { michael@0: int month = mTempDate.get(Calendar.MONTH); michael@0: mTempDate.set(Calendar.YEAR,newVal); michael@0: // Changing the year shouldn't change the month. (in case of non-leap year a Feb 29) michael@0: // change the day instead; michael@0: if (month != mTempDate.get(Calendar.MONTH)){ michael@0: mTempDate.set(Calendar.MONTH, month); michael@0: mTempDate.set(Calendar.DAY_OF_MONTH, michael@0: mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH)); michael@0: } michael@0: } else if (picker == mHourSpinner && mHourEnabled) { michael@0: if (mIs12HourMode) { michael@0: setTempDate(Calendar.HOUR, oldVal, newVal, 1, 12); michael@0: } else { michael@0: setTempDate(Calendar.HOUR_OF_DAY, oldVal, newVal, 0, 23); michael@0: } michael@0: } else if (picker == mMinuteSpinner && mMinuteEnabled) { michael@0: setTempDate(Calendar.MINUTE, oldVal, newVal, 0, 59); michael@0: } else if (picker == mAMPMSpinner && mHourEnabled) { michael@0: mTempDate.set(Calendar.AM_PM,newVal); michael@0: } else { michael@0: throw new IllegalArgumentException(); michael@0: } michael@0: } else { michael@0: if (DEBUG) Log.d(LOGTAG,"Sdk version < 10, using old behavior"); michael@0: if (picker == mDaySpinner && mDayEnabled){ michael@0: mTempDate.set(Calendar.DAY_OF_MONTH, newVal); michael@0: } else if (picker == mMonthSpinner && mMonthEnabled){ michael@0: mTempDate.set(Calendar.MONTH, newVal); michael@0: if (mTempDate.get(Calendar.MONTH) == newVal+1){ michael@0: mTempDate.set(Calendar.MONTH, newVal); michael@0: mTempDate.set(Calendar.DAY_OF_MONTH, michael@0: mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH)); michael@0: } michael@0: } else if (picker == mWeekSpinner){ michael@0: mTempDate.set(Calendar.WEEK_OF_YEAR, newVal); michael@0: } else if (picker == mYearSpinner && mYearEnabled){ michael@0: int month = mTempDate.get(Calendar.MONTH); michael@0: mTempDate.set(Calendar.YEAR, newVal); michael@0: if (month != mTempDate.get(Calendar.MONTH)) { michael@0: mTempDate.set(Calendar.MONTH, month); michael@0: mTempDate.set(Calendar.DAY_OF_MONTH, michael@0: mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH)); michael@0: } michael@0: } else if (picker == mHourSpinner && mHourEnabled){ michael@0: if (mIs12HourMode) { michael@0: mTempDate.set(Calendar.HOUR, newVal); michael@0: } else { michael@0: mTempDate.set(Calendar.HOUR_OF_DAY, newVal); michael@0: } michael@0: } else if (picker == mMinuteSpinner && mMinuteEnabled){ michael@0: mTempDate.set(Calendar.MINUTE, newVal); michael@0: } else if (picker == mAMPMSpinner && mHourEnabled) { michael@0: mTempDate.set(Calendar.AM_PM, newVal); michael@0: } else { michael@0: throw new IllegalArgumentException(); michael@0: } michael@0: } michael@0: setDate(mTempDate); michael@0: if (mDayEnabled) { michael@0: mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); michael@0: } michael@0: if(mWeekEnabled) { michael@0: mWeekSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.WEEK_OF_YEAR)); michael@0: } michael@0: updateCalendar(); michael@0: updateSpinners(); michael@0: notifyDateChanged(); michael@0: } michael@0: michael@0: private void setTempDate(int field, int oldVal, int newVal, int min, int max) { michael@0: if (oldVal == max && newVal == min ) { michael@0: mTempDate.add(field, 1); michael@0: } else if (oldVal == min && newVal == max) { michael@0: mTempDate.add(field, -1); michael@0: } else { michael@0: mTempDate.add(field, newVal - oldVal); michael@0: } michael@0: } michael@0: } michael@0: michael@0: private static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() { michael@0: final StringBuilder mBuilder = new StringBuilder(); michael@0: michael@0: final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US); michael@0: michael@0: final Object[] mArgs = new Object[1]; michael@0: michael@0: @Override michael@0: public String format(int value) { michael@0: mArgs[0] = value; michael@0: mBuilder.delete(0, mBuilder.length()); michael@0: mFmt.format("%02d", mArgs); michael@0: return mFmt.toString(); michael@0: } michael@0: }; michael@0: michael@0: private void displayPickers() { michael@0: setWeekShown(false); michael@0: set12HourShown(mIs12HourMode); michael@0: if (mState == PickersState.DATETIME) { michael@0: return; michael@0: } michael@0: setHourShown(false); michael@0: setMinuteShown(false); michael@0: if (mState == PickersState.WEEK) { michael@0: setDayShown(false); michael@0: setMonthShown(false); michael@0: setWeekShown(true); michael@0: } else if (mState == PickersState.MONTH) { michael@0: setDayShown(false); michael@0: } michael@0: } michael@0: michael@0: public DateTimePicker(Context context) { michael@0: this(context, "", "", PickersState.DATE); michael@0: } michael@0: michael@0: public DateTimePicker(Context context, String dateFormat, String dateTimeValue, PickersState state) { michael@0: super(context); michael@0: if (Build.VERSION.SDK_INT < 11) { michael@0: throw new UnsupportedOperationException("Custom DateTimePicker is only available for SDK > 10"); michael@0: } michael@0: setCurrentLocale(Locale.getDefault()); michael@0: mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1); michael@0: mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31); michael@0: mState = state; michael@0: LayoutInflater inflater = LayoutInflater.from(context); michael@0: inflater.inflate(R.layout.datetime_picker, this, true); michael@0: michael@0: mOnChangeListener = new OnValueChangeListener(); michael@0: michael@0: mDateSpinners = (LinearLayout)findViewById(R.id.date_spinners); michael@0: mTimeSpinners = (LinearLayout)findViewById(R.id.time_spinners); michael@0: mSpinners = (LinearLayout)findViewById(R.id.spinners); michael@0: mPickers = (LinearLayout)findViewById(R.id.datetime_picker); michael@0: michael@0: // We will display differently according to the screen size width. michael@0: WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); michael@0: Display display = wm.getDefaultDisplay(); michael@0: DisplayMetrics dm = new DisplayMetrics(); michael@0: display.getMetrics(dm); michael@0: mScreenWidth = display.getWidth() / dm.densityDpi; michael@0: mScreenHeight = display.getHeight() / dm.densityDpi; michael@0: if (DEBUG) Log.d(LOGTAG, "screen width: " + mScreenWidth + " screen height: " + mScreenHeight); michael@0: michael@0: // If we're displaying a date, the screen is wide enought (and if we're using a sdk where the calendar view exists) michael@0: // then display a calendar. michael@0: if ((mState == PickersState.DATE || mState == PickersState.DATETIME) && michael@0: Build.VERSION.SDK_INT > 10 && mScreenWidth >= SCREEN_SIZE_THRESHOLD) { michael@0: if (DEBUG) Log.d(LOGTAG,"SDK > 10 and screen wide enough, displaying calendar"); michael@0: mCalendar = new CalendarView(context); michael@0: mCalendar.setVisibility(GONE); michael@0: michael@0: LayoutParams layoutParams = new LayoutParams(250,280); michael@0: mCalendar.setLayoutParams(layoutParams); michael@0: mCalendar.setFocusable(true); michael@0: mCalendar.setFocusableInTouchMode(true); michael@0: mCalendar.setMaxDate(mMaxDate.getTimeInMillis()); michael@0: mCalendar.setMinDate(mMinDate.getTimeInMillis()); michael@0: michael@0: mCalendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() { michael@0: @Override michael@0: public void onSelectedDayChange( michael@0: CalendarView view, int year, int month, int monthDay) { michael@0: mTempDate.set(year, month, monthDay); michael@0: setDate(mTempDate); michael@0: notifyDateChanged(); michael@0: } michael@0: }); michael@0: michael@0: mPickers.addView(mCalendar); michael@0: } else { michael@0: // If the screen is more wide than high, we are displaying daye and time spinners, michael@0: // and if there is no calendar displayed, michael@0: // we should display the fields in one row. michael@0: if (mScreenWidth > mScreenHeight && mState == PickersState.DATETIME) { michael@0: mSpinners.setOrientation(LinearLayout.HORIZONTAL); michael@0: } michael@0: mCalendar = null; michael@0: } michael@0: michael@0: // Find the initial date from the constructor arguments. michael@0: try { michael@0: if (!dateTimeValue.equals("")) { michael@0: mTempDate.setTime(new SimpleDateFormat(dateFormat).parse(dateTimeValue)); michael@0: } else { michael@0: mTempDate.setTimeInMillis(System.currentTimeMillis()); michael@0: } michael@0: } catch (Exception ex) { michael@0: Log.e(LOGTAG, "Error parsing format string: " + ex); michael@0: mTempDate.setTimeInMillis(System.currentTimeMillis()); michael@0: } michael@0: michael@0: // Initialize all spinners. michael@0: mDaySpinner = setupSpinner(R.id.day, 1, michael@0: mTempDate.get(Calendar.DAY_OF_MONTH)); michael@0: mDaySpinner.setFormatter(TWO_DIGIT_FORMATTER); michael@0: mDaySpinnerInput = (EditText) mDaySpinner.getChildAt(1); michael@0: michael@0: mMonthSpinner = setupSpinner(R.id.month, 1, michael@0: mTempDate.get(Calendar.MONTH)); michael@0: mMonthSpinner.setFormatter(TWO_DIGIT_FORMATTER); michael@0: mMonthSpinner.setDisplayedValues(mShortMonths); michael@0: mMonthSpinnerInput = (EditText) mMonthSpinner.getChildAt(1); michael@0: michael@0: mWeekSpinner = setupSpinner(R.id.week, 1, michael@0: mTempDate.get(Calendar.WEEK_OF_YEAR)); michael@0: mWeekSpinner.setFormatter(TWO_DIGIT_FORMATTER); michael@0: mWeekSpinnerInput = (EditText) mWeekSpinner.getChildAt(1); michael@0: michael@0: mYearSpinner = setupSpinner(R.id.year, DEFAULT_START_YEAR, michael@0: DEFAULT_END_YEAR); michael@0: mYearSpinnerInput = (EditText) mYearSpinner.getChildAt(1); michael@0: michael@0: mAMPMSpinner = setupSpinner(R.id.ampm, 0, 1); michael@0: mAMPMSpinner.setFormatter(TWO_DIGIT_FORMATTER); michael@0: michael@0: if (mIs12HourMode) { michael@0: mHourSpinner = setupSpinner(R.id.hour, 1, 12); michael@0: mAMPMSpinnerInput = (EditText) mAMPMSpinner.getChildAt(1); michael@0: mAMPMSpinner.setDisplayedValues(mShortAMPMs); michael@0: } else { michael@0: mHourSpinner = setupSpinner(R.id.hour, 0, 23); michael@0: mAMPMSpinnerInput = null; michael@0: } michael@0: michael@0: mHourSpinner.setFormatter(TWO_DIGIT_FORMATTER); michael@0: mHourSpinnerInput = (EditText) mHourSpinner.getChildAt(1); michael@0: michael@0: mMinuteSpinner = setupSpinner(R.id.minute, 0, 59); michael@0: mMinuteSpinner.setFormatter(TWO_DIGIT_FORMATTER); michael@0: mMinuteSpinnerInput = (EditText) mMinuteSpinner.getChildAt(1); michael@0: michael@0: // The order in which the spinners are displayed are locale-dependent michael@0: reorderDateSpinners(); michael@0: // Set the date to the initial date. Since this date can come from the user, michael@0: // it can fire an exception (out-of-bound date) michael@0: try { michael@0: updateDate(mTempDate); michael@0: } catch (Exception ex) { } michael@0: michael@0: // Display only the pickers needed for the current state. michael@0: displayPickers(); michael@0: } michael@0: michael@0: public NumberPicker setupSpinner(int id, int min, int max) { michael@0: NumberPicker mSpinner = (NumberPicker) findViewById(id); michael@0: mSpinner.setMinValue(min); michael@0: mSpinner.setMaxValue(max); michael@0: mSpinner.setOnValueChangedListener(mOnChangeListener); michael@0: mSpinner.setOnLongPressUpdateInterval(100); michael@0: return mSpinner; michael@0: } michael@0: michael@0: public long getTimeInMillis(){ michael@0: return mCurrentDate.getTimeInMillis(); michael@0: } michael@0: michael@0: private void reorderDateSpinners() { michael@0: mDateSpinners.removeAllViews(); michael@0: char[] order = DateFormat.getDateFormatOrder(getContext()); michael@0: final int spinnerCount = order.length; michael@0: for (int i = 0; i < spinnerCount; i++) { michael@0: switch (order[i]) { michael@0: case DateFormat.DATE: michael@0: mDateSpinners.addView(mDaySpinner); michael@0: break; michael@0: case DateFormat.MONTH: michael@0: mDateSpinners.addView(mMonthSpinner); michael@0: break; michael@0: case DateFormat.YEAR: michael@0: mDateSpinners.addView(mYearSpinner); michael@0: break; michael@0: default: michael@0: throw new IllegalArgumentException(); michael@0: } michael@0: } michael@0: mDateSpinners.addView(mWeekSpinner); michael@0: } michael@0: michael@0: private void setDate(Calendar calendar){ michael@0: mCurrentDate = mTempDate; michael@0: if (mCurrentDate.before(mMinDate)) { michael@0: mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); michael@0: } else if (mCurrentDate.after(mMaxDate)) { michael@0: mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); michael@0: } michael@0: } michael@0: michael@0: private void updateInputState() { michael@0: InputMethodManager inputMethodManager = (InputMethodManager) michael@0: getContext().getSystemService(Context.INPUT_METHOD_SERVICE); michael@0: if (mYearEnabled && inputMethodManager.isActive(mYearSpinnerInput)) { michael@0: mYearSpinnerInput.clearFocus(); michael@0: inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); michael@0: } else if (mMonthEnabled && inputMethodManager.isActive(mMonthSpinnerInput)) { michael@0: mMonthSpinnerInput.clearFocus(); michael@0: inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); michael@0: } else if (mDayEnabled && inputMethodManager.isActive(mDaySpinnerInput)) { michael@0: mDaySpinnerInput.clearFocus(); michael@0: inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); michael@0: } else if (mHourEnabled && inputMethodManager.isActive(mHourSpinnerInput)) { michael@0: mHourSpinnerInput.clearFocus(); michael@0: inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); michael@0: } else if (mMinuteEnabled && inputMethodManager.isActive(mMinuteSpinnerInput)) { michael@0: mMinuteSpinnerInput.clearFocus(); michael@0: inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); michael@0: } michael@0: } michael@0: michael@0: private void updateSpinners() { michael@0: if (mDayEnabled) { michael@0: if (mCurrentDate.equals(mMinDate)) { michael@0: mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); michael@0: mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); michael@0: } else if (mCurrentDate.equals(mMaxDate)) { michael@0: mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH)); michael@0: mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); michael@0: } else { michael@0: mDaySpinner.setMinValue(1); michael@0: mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); michael@0: } michael@0: mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); michael@0: } michael@0: michael@0: if (mWeekEnabled) { michael@0: mWeekSpinner.setMinValue(1); michael@0: mWeekSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.WEEK_OF_YEAR)); michael@0: mWeekSpinner.setValue(mCurrentDate.get(Calendar.WEEK_OF_YEAR)); michael@0: } michael@0: michael@0: if (mMonthEnabled) { michael@0: mMonthSpinner.setDisplayedValues(null); michael@0: if (mCurrentDate.equals(mMinDate)) { michael@0: mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH)); michael@0: mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH)); michael@0: } else if (mCurrentDate.equals(mMaxDate)) { michael@0: mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH)); michael@0: mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH)); michael@0: } else { michael@0: mMonthSpinner.setMinValue(Calendar.JANUARY); michael@0: mMonthSpinner.setMaxValue(Calendar.DECEMBER); michael@0: } michael@0: michael@0: String[] displayedValues = Arrays.copyOfRange(mShortMonths, michael@0: mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1); michael@0: mMonthSpinner.setDisplayedValues(displayedValues); michael@0: mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH)); michael@0: } michael@0: michael@0: if (mYearEnabled) { michael@0: mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR)); michael@0: mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR)); michael@0: mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR)); michael@0: } michael@0: michael@0: if (mHourEnabled) { michael@0: if (mIs12HourMode) { michael@0: mHourSpinner.setValue(mCurrentDate.get(Calendar.HOUR)); michael@0: mAMPMSpinner.setValue(mCurrentDate.get(Calendar.AM_PM)); michael@0: mAMPMSpinner.setDisplayedValues(mShortAMPMs); michael@0: } else { michael@0: mHourSpinner.setValue(mCurrentDate.get(Calendar.HOUR_OF_DAY)); michael@0: } michael@0: } michael@0: if (mMinuteEnabled) { michael@0: mMinuteSpinner.setValue(mCurrentDate.get(Calendar.MINUTE)); michael@0: } michael@0: } michael@0: michael@0: private void updateCalendar() { michael@0: if (mCalendarEnabled){ michael@0: mCalendar.setDate(mCurrentDate.getTimeInMillis(), false, false); michael@0: } michael@0: } michael@0: michael@0: private void notifyDateChanged() { michael@0: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); michael@0: } michael@0: michael@0: public void toggleCalendar(boolean shown) { michael@0: if ((mState != PickersState.DATE && mState != PickersState.DATETIME) || michael@0: Build.VERSION.SDK_INT < 11 || mScreenWidth < SCREEN_SIZE_THRESHOLD) { michael@0: if (DEBUG) Log.d(LOGTAG,"Cannot display calendar on this device, in this state" + michael@0: ": screen width :"+mScreenWidth); michael@0: return; michael@0: } michael@0: if (shown){ michael@0: mCalendarEnabled = true; michael@0: mCalendar.setVisibility(VISIBLE); michael@0: setYearShown(false); michael@0: setWeekShown(false); michael@0: setMonthShown(false); michael@0: setDayShown(false); michael@0: } else { michael@0: mCalendar.setVisibility(GONE); michael@0: setYearShown(true); michael@0: setMonthShown(true); michael@0: setDayShown(true); michael@0: mSpinners.setOrientation(LinearLayout.HORIZONTAL); michael@0: mCalendarEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void setYearShown(boolean shown) { michael@0: if (shown) { michael@0: toggleCalendar(false); michael@0: mYearSpinner.setVisibility(VISIBLE); michael@0: mYearEnabled = true; michael@0: } else { michael@0: mYearSpinner.setVisibility(GONE); michael@0: mYearEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void setWeekShown(boolean shown) { michael@0: if (shown) { michael@0: toggleCalendar(false); michael@0: mWeekSpinner.setVisibility(VISIBLE); michael@0: mWeekEnabled = true; michael@0: } else { michael@0: mWeekSpinner.setVisibility(GONE); michael@0: mWeekEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void setMonthShown(boolean shown) { michael@0: if (shown) { michael@0: toggleCalendar(false); michael@0: mMonthSpinner.setVisibility(VISIBLE); michael@0: mMonthEnabled = true; michael@0: } else { michael@0: mMonthSpinner.setVisibility(GONE); michael@0: mMonthEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void setDayShown(boolean shown) { michael@0: if (shown) { michael@0: toggleCalendar(false); michael@0: mDaySpinner.setVisibility(VISIBLE); michael@0: mDayEnabled = true; michael@0: } else { michael@0: mDaySpinner.setVisibility(GONE); michael@0: mDayEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void set12HourShown(boolean shown) { michael@0: if (shown) { michael@0: mAMPMSpinner.setVisibility(VISIBLE); michael@0: } else { michael@0: mAMPMSpinner.setVisibility(GONE); michael@0: } michael@0: } michael@0: michael@0: private void setHourShown(boolean shown) { michael@0: if (shown) { michael@0: mHourSpinner.setVisibility(VISIBLE); michael@0: mHourEnabled= true; michael@0: } else { michael@0: mHourSpinner.setVisibility(GONE); michael@0: mAMPMSpinner.setVisibility(GONE); michael@0: mTimeSpinners.setVisibility(GONE); michael@0: mHourEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void setMinuteShown(boolean shown) { michael@0: if (shown) { michael@0: mMinuteSpinner.setVisibility(VISIBLE); michael@0: mTimeSpinners.findViewById(R.id.mincolon).setVisibility(VISIBLE); michael@0: mMinuteEnabled= true; michael@0: } else { michael@0: mMinuteSpinner.setVisibility(GONE); michael@0: mTimeSpinners.findViewById(R.id.mincolon).setVisibility(GONE); michael@0: mMinuteEnabled = false; michael@0: } michael@0: } michael@0: michael@0: private void setCurrentLocale(Locale locale) { michael@0: if (locale.equals(mCurrentLocale)) { michael@0: return; michael@0: } michael@0: michael@0: mCurrentLocale = locale; michael@0: mIs12HourMode = !DateFormat.is24HourFormat(getContext()); michael@0: mTempDate = getCalendarForLocale(mTempDate, locale); michael@0: mMinDate = getCalendarForLocale(mMinDate, locale); michael@0: mMaxDate = getCalendarForLocale(mMaxDate, locale); michael@0: mCurrentDate = getCalendarForLocale(mCurrentDate, locale); michael@0: michael@0: mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1; michael@0: michael@0: mShortAMPMs = new String[2]; michael@0: mShortAMPMs[0] = DateUtils.getAMPMString(Calendar.AM); michael@0: mShortAMPMs[1] = DateUtils.getAMPMString(Calendar.PM); michael@0: michael@0: mShortMonths = new String[mNumberOfMonths]; michael@0: for (int i = 0; i < mNumberOfMonths; i++) { michael@0: mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i, michael@0: DateUtils.LENGTH_MEDIUM); michael@0: } michael@0: } michael@0: michael@0: private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) { michael@0: if (oldCalendar == null) { michael@0: return Calendar.getInstance(locale); michael@0: } else { michael@0: final long currentTimeMillis = oldCalendar.getTimeInMillis(); michael@0: Calendar newCalendar = Calendar.getInstance(locale); michael@0: newCalendar.setTimeInMillis(currentTimeMillis); michael@0: return newCalendar; michael@0: } michael@0: } michael@0: michael@0: public void updateDate(Calendar calendar) { michael@0: if (mCurrentDate.equals(calendar)) { michael@0: return; michael@0: } michael@0: mCurrentDate.setTimeInMillis(calendar.getTimeInMillis()); michael@0: if (mCurrentDate.before(mMinDate)) { michael@0: mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); michael@0: } else if (mCurrentDate.after(mMaxDate)) { michael@0: mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); michael@0: } michael@0: updateSpinners(); michael@0: notifyDateChanged(); michael@0: } michael@0: michael@0: } michael@0: