Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /*
2 * Copyright (C) 2007 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 */
17 package org.mozilla.gecko.widget;
19 import org.mozilla.gecko.R;
21 import android.content.Context;
22 import android.os.Build;
23 import android.text.format.DateFormat;
24 import android.text.format.DateUtils;
25 import android.util.DisplayMetrics;
26 import android.util.Log;
27 import android.view.Display;
28 import android.view.LayoutInflater;
29 import android.view.WindowManager;
30 import android.view.accessibility.AccessibilityEvent;
31 import android.view.inputmethod.InputMethodManager;
32 import android.widget.CalendarView;
33 import android.widget.EditText;
34 import android.widget.FrameLayout;
35 import android.widget.LinearLayout;
36 import android.widget.NumberPicker;
38 import java.text.SimpleDateFormat;
39 import java.util.Arrays;
40 import java.util.Calendar;
41 import java.util.Locale;
43 public class DateTimePicker extends FrameLayout {
45 private static final boolean DEBUG = true;
46 private static final String LOGTAG = "GeckoDateTimePicker";
47 private static final String DATE_FORMAT = "MM/dd/yyyy";
48 private static final int DEFAULT_START_YEAR = 1;
49 private static final int DEFAULT_END_YEAR = 9999;
50 // Minimal screen width (in inches) for which we can show the calendar;
51 private static final int SCREEN_SIZE_THRESHOLD = 5;
52 private boolean mYearEnabled = true;
53 private boolean mMonthEnabled = true;
54 private boolean mWeekEnabled = false;
55 private boolean mDayEnabled = true;
56 private boolean mHourEnabled = true;
57 private boolean mMinuteEnabled = true;
58 private boolean mCalendarEnabled = false;
59 private boolean mIs12HourMode;
60 // Size of the screen in inches;
61 private int mScreenWidth;
62 private int mScreenHeight;
63 private OnValueChangeListener mOnChangeListener;
64 private final LinearLayout mPickers;
65 private final LinearLayout mDateSpinners;
66 private final LinearLayout mTimeSpinners;
67 private final LinearLayout mSpinners;
68 private final NumberPicker mDaySpinner;
69 private final NumberPicker mMonthSpinner;
70 private final NumberPicker mWeekSpinner;
71 private final NumberPicker mYearSpinner;
72 private final NumberPicker mHourSpinner;
73 private final NumberPicker mMinuteSpinner;
74 private final NumberPicker mAMPMSpinner;
75 private final CalendarView mCalendar;
76 private final EditText mDaySpinnerInput;
77 private final EditText mMonthSpinnerInput;
78 private final EditText mWeekSpinnerInput;
79 private final EditText mYearSpinnerInput;
80 private final EditText mHourSpinnerInput;
81 private final EditText mMinuteSpinnerInput;
82 private final EditText mAMPMSpinnerInput;
83 private Locale mCurrentLocale;
84 private String[] mShortMonths;
85 private String[] mShortAMPMs;
86 private int mNumberOfMonths;
87 private Calendar mTempDate;
88 private Calendar mMinDate;
89 private Calendar mMaxDate;
90 private Calendar mCurrentDate;
91 private PickersState mState;
93 public static enum PickersState { DATE, MONTH, WEEK, TIME, DATETIME };
95 public class OnValueChangeListener implements NumberPicker.OnValueChangeListener {
96 @Override
97 public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
98 updateInputState();
99 mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
100 boolean newBehavior = (Build.VERSION.SDK_INT > 10);
101 if (newBehavior) {
102 if (DEBUG) Log.d(LOGTAG, "Sdk version > 10, using new behavior");
103 //The native date picker widget on these sdks increment
104 //the next field when one field reach the maximum
105 if (picker == mDaySpinner && mDayEnabled) {
106 int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
107 int old = mTempDate.get(Calendar.DAY_OF_MONTH);
108 setTempDate(Calendar.DAY_OF_MONTH, old, newVal, 1, maxDayOfMonth);
109 } else if (picker == mMonthSpinner && mMonthEnabled) {
110 int old = mTempDate.get(Calendar.MONTH);
111 setTempDate(Calendar.MONTH, old, newVal, Calendar.JANUARY, Calendar.DECEMBER);
112 } else if (picker == mWeekSpinner) {
113 int old = mTempDate.get(Calendar.WEEK_OF_YEAR);
114 int maxWeekOfYear = mTempDate.getActualMaximum(Calendar.WEEK_OF_YEAR);
115 setTempDate(Calendar.WEEK_OF_YEAR, old, newVal, 0, maxWeekOfYear);
116 } else if (picker == mYearSpinner && mYearEnabled) {
117 int month = mTempDate.get(Calendar.MONTH);
118 mTempDate.set(Calendar.YEAR,newVal);
119 // Changing the year shouldn't change the month. (in case of non-leap year a Feb 29)
120 // change the day instead;
121 if (month != mTempDate.get(Calendar.MONTH)){
122 mTempDate.set(Calendar.MONTH, month);
123 mTempDate.set(Calendar.DAY_OF_MONTH,
124 mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH));
125 }
126 } else if (picker == mHourSpinner && mHourEnabled) {
127 if (mIs12HourMode) {
128 setTempDate(Calendar.HOUR, oldVal, newVal, 1, 12);
129 } else {
130 setTempDate(Calendar.HOUR_OF_DAY, oldVal, newVal, 0, 23);
131 }
132 } else if (picker == mMinuteSpinner && mMinuteEnabled) {
133 setTempDate(Calendar.MINUTE, oldVal, newVal, 0, 59);
134 } else if (picker == mAMPMSpinner && mHourEnabled) {
135 mTempDate.set(Calendar.AM_PM,newVal);
136 } else {
137 throw new IllegalArgumentException();
138 }
139 } else {
140 if (DEBUG) Log.d(LOGTAG,"Sdk version < 10, using old behavior");
141 if (picker == mDaySpinner && mDayEnabled){
142 mTempDate.set(Calendar.DAY_OF_MONTH, newVal);
143 } else if (picker == mMonthSpinner && mMonthEnabled){
144 mTempDate.set(Calendar.MONTH, newVal);
145 if (mTempDate.get(Calendar.MONTH) == newVal+1){
146 mTempDate.set(Calendar.MONTH, newVal);
147 mTempDate.set(Calendar.DAY_OF_MONTH,
148 mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH));
149 }
150 } else if (picker == mWeekSpinner){
151 mTempDate.set(Calendar.WEEK_OF_YEAR, newVal);
152 } else if (picker == mYearSpinner && mYearEnabled){
153 int month = mTempDate.get(Calendar.MONTH);
154 mTempDate.set(Calendar.YEAR, newVal);
155 if (month != mTempDate.get(Calendar.MONTH)) {
156 mTempDate.set(Calendar.MONTH, month);
157 mTempDate.set(Calendar.DAY_OF_MONTH,
158 mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH));
159 }
160 } else if (picker == mHourSpinner && mHourEnabled){
161 if (mIs12HourMode) {
162 mTempDate.set(Calendar.HOUR, newVal);
163 } else {
164 mTempDate.set(Calendar.HOUR_OF_DAY, newVal);
165 }
166 } else if (picker == mMinuteSpinner && mMinuteEnabled){
167 mTempDate.set(Calendar.MINUTE, newVal);
168 } else if (picker == mAMPMSpinner && mHourEnabled) {
169 mTempDate.set(Calendar.AM_PM, newVal);
170 } else {
171 throw new IllegalArgumentException();
172 }
173 }
174 setDate(mTempDate);
175 if (mDayEnabled) {
176 mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
177 }
178 if(mWeekEnabled) {
179 mWeekSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.WEEK_OF_YEAR));
180 }
181 updateCalendar();
182 updateSpinners();
183 notifyDateChanged();
184 }
186 private void setTempDate(int field, int oldVal, int newVal, int min, int max) {
187 if (oldVal == max && newVal == min ) {
188 mTempDate.add(field, 1);
189 } else if (oldVal == min && newVal == max) {
190 mTempDate.add(field, -1);
191 } else {
192 mTempDate.add(field, newVal - oldVal);
193 }
194 }
195 }
197 private static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() {
198 final StringBuilder mBuilder = new StringBuilder();
200 final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US);
202 final Object[] mArgs = new Object[1];
204 @Override
205 public String format(int value) {
206 mArgs[0] = value;
207 mBuilder.delete(0, mBuilder.length());
208 mFmt.format("%02d", mArgs);
209 return mFmt.toString();
210 }
211 };
213 private void displayPickers() {
214 setWeekShown(false);
215 set12HourShown(mIs12HourMode);
216 if (mState == PickersState.DATETIME) {
217 return;
218 }
219 setHourShown(false);
220 setMinuteShown(false);
221 if (mState == PickersState.WEEK) {
222 setDayShown(false);
223 setMonthShown(false);
224 setWeekShown(true);
225 } else if (mState == PickersState.MONTH) {
226 setDayShown(false);
227 }
228 }
230 public DateTimePicker(Context context) {
231 this(context, "", "", PickersState.DATE);
232 }
234 public DateTimePicker(Context context, String dateFormat, String dateTimeValue, PickersState state) {
235 super(context);
236 if (Build.VERSION.SDK_INT < 11) {
237 throw new UnsupportedOperationException("Custom DateTimePicker is only available for SDK > 10");
238 }
239 setCurrentLocale(Locale.getDefault());
240 mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1);
241 mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31);
242 mState = state;
243 LayoutInflater inflater = LayoutInflater.from(context);
244 inflater.inflate(R.layout.datetime_picker, this, true);
246 mOnChangeListener = new OnValueChangeListener();
248 mDateSpinners = (LinearLayout)findViewById(R.id.date_spinners);
249 mTimeSpinners = (LinearLayout)findViewById(R.id.time_spinners);
250 mSpinners = (LinearLayout)findViewById(R.id.spinners);
251 mPickers = (LinearLayout)findViewById(R.id.datetime_picker);
253 // We will display differently according to the screen size width.
254 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
255 Display display = wm.getDefaultDisplay();
256 DisplayMetrics dm = new DisplayMetrics();
257 display.getMetrics(dm);
258 mScreenWidth = display.getWidth() / dm.densityDpi;
259 mScreenHeight = display.getHeight() / dm.densityDpi;
260 if (DEBUG) Log.d(LOGTAG, "screen width: " + mScreenWidth + " screen height: " + mScreenHeight);
262 // If we're displaying a date, the screen is wide enought (and if we're using a sdk where the calendar view exists)
263 // then display a calendar.
264 if ((mState == PickersState.DATE || mState == PickersState.DATETIME) &&
265 Build.VERSION.SDK_INT > 10 && mScreenWidth >= SCREEN_SIZE_THRESHOLD) {
266 if (DEBUG) Log.d(LOGTAG,"SDK > 10 and screen wide enough, displaying calendar");
267 mCalendar = new CalendarView(context);
268 mCalendar.setVisibility(GONE);
270 LayoutParams layoutParams = new LayoutParams(250,280);
271 mCalendar.setLayoutParams(layoutParams);
272 mCalendar.setFocusable(true);
273 mCalendar.setFocusableInTouchMode(true);
274 mCalendar.setMaxDate(mMaxDate.getTimeInMillis());
275 mCalendar.setMinDate(mMinDate.getTimeInMillis());
277 mCalendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
278 @Override
279 public void onSelectedDayChange(
280 CalendarView view, int year, int month, int monthDay) {
281 mTempDate.set(year, month, monthDay);
282 setDate(mTempDate);
283 notifyDateChanged();
284 }
285 });
287 mPickers.addView(mCalendar);
288 } else {
289 // If the screen is more wide than high, we are displaying daye and time spinners,
290 // and if there is no calendar displayed,
291 // we should display the fields in one row.
292 if (mScreenWidth > mScreenHeight && mState == PickersState.DATETIME) {
293 mSpinners.setOrientation(LinearLayout.HORIZONTAL);
294 }
295 mCalendar = null;
296 }
298 // Find the initial date from the constructor arguments.
299 try {
300 if (!dateTimeValue.equals("")) {
301 mTempDate.setTime(new SimpleDateFormat(dateFormat).parse(dateTimeValue));
302 } else {
303 mTempDate.setTimeInMillis(System.currentTimeMillis());
304 }
305 } catch (Exception ex) {
306 Log.e(LOGTAG, "Error parsing format string: " + ex);
307 mTempDate.setTimeInMillis(System.currentTimeMillis());
308 }
310 // Initialize all spinners.
311 mDaySpinner = setupSpinner(R.id.day, 1,
312 mTempDate.get(Calendar.DAY_OF_MONTH));
313 mDaySpinner.setFormatter(TWO_DIGIT_FORMATTER);
314 mDaySpinnerInput = (EditText) mDaySpinner.getChildAt(1);
316 mMonthSpinner = setupSpinner(R.id.month, 1,
317 mTempDate.get(Calendar.MONTH));
318 mMonthSpinner.setFormatter(TWO_DIGIT_FORMATTER);
319 mMonthSpinner.setDisplayedValues(mShortMonths);
320 mMonthSpinnerInput = (EditText) mMonthSpinner.getChildAt(1);
322 mWeekSpinner = setupSpinner(R.id.week, 1,
323 mTempDate.get(Calendar.WEEK_OF_YEAR));
324 mWeekSpinner.setFormatter(TWO_DIGIT_FORMATTER);
325 mWeekSpinnerInput = (EditText) mWeekSpinner.getChildAt(1);
327 mYearSpinner = setupSpinner(R.id.year, DEFAULT_START_YEAR,
328 DEFAULT_END_YEAR);
329 mYearSpinnerInput = (EditText) mYearSpinner.getChildAt(1);
331 mAMPMSpinner = setupSpinner(R.id.ampm, 0, 1);
332 mAMPMSpinner.setFormatter(TWO_DIGIT_FORMATTER);
334 if (mIs12HourMode) {
335 mHourSpinner = setupSpinner(R.id.hour, 1, 12);
336 mAMPMSpinnerInput = (EditText) mAMPMSpinner.getChildAt(1);
337 mAMPMSpinner.setDisplayedValues(mShortAMPMs);
338 } else {
339 mHourSpinner = setupSpinner(R.id.hour, 0, 23);
340 mAMPMSpinnerInput = null;
341 }
343 mHourSpinner.setFormatter(TWO_DIGIT_FORMATTER);
344 mHourSpinnerInput = (EditText) mHourSpinner.getChildAt(1);
346 mMinuteSpinner = setupSpinner(R.id.minute, 0, 59);
347 mMinuteSpinner.setFormatter(TWO_DIGIT_FORMATTER);
348 mMinuteSpinnerInput = (EditText) mMinuteSpinner.getChildAt(1);
350 // The order in which the spinners are displayed are locale-dependent
351 reorderDateSpinners();
352 // Set the date to the initial date. Since this date can come from the user,
353 // it can fire an exception (out-of-bound date)
354 try {
355 updateDate(mTempDate);
356 } catch (Exception ex) { }
358 // Display only the pickers needed for the current state.
359 displayPickers();
360 }
362 public NumberPicker setupSpinner(int id, int min, int max) {
363 NumberPicker mSpinner = (NumberPicker) findViewById(id);
364 mSpinner.setMinValue(min);
365 mSpinner.setMaxValue(max);
366 mSpinner.setOnValueChangedListener(mOnChangeListener);
367 mSpinner.setOnLongPressUpdateInterval(100);
368 return mSpinner;
369 }
371 public long getTimeInMillis(){
372 return mCurrentDate.getTimeInMillis();
373 }
375 private void reorderDateSpinners() {
376 mDateSpinners.removeAllViews();
377 char[] order = DateFormat.getDateFormatOrder(getContext());
378 final int spinnerCount = order.length;
379 for (int i = 0; i < spinnerCount; i++) {
380 switch (order[i]) {
381 case DateFormat.DATE:
382 mDateSpinners.addView(mDaySpinner);
383 break;
384 case DateFormat.MONTH:
385 mDateSpinners.addView(mMonthSpinner);
386 break;
387 case DateFormat.YEAR:
388 mDateSpinners.addView(mYearSpinner);
389 break;
390 default:
391 throw new IllegalArgumentException();
392 }
393 }
394 mDateSpinners.addView(mWeekSpinner);
395 }
397 private void setDate(Calendar calendar){
398 mCurrentDate = mTempDate;
399 if (mCurrentDate.before(mMinDate)) {
400 mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
401 } else if (mCurrentDate.after(mMaxDate)) {
402 mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
403 }
404 }
406 private void updateInputState() {
407 InputMethodManager inputMethodManager = (InputMethodManager)
408 getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
409 if (mYearEnabled && inputMethodManager.isActive(mYearSpinnerInput)) {
410 mYearSpinnerInput.clearFocus();
411 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
412 } else if (mMonthEnabled && inputMethodManager.isActive(mMonthSpinnerInput)) {
413 mMonthSpinnerInput.clearFocus();
414 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
415 } else if (mDayEnabled && inputMethodManager.isActive(mDaySpinnerInput)) {
416 mDaySpinnerInput.clearFocus();
417 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
418 } else if (mHourEnabled && inputMethodManager.isActive(mHourSpinnerInput)) {
419 mHourSpinnerInput.clearFocus();
420 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
421 } else if (mMinuteEnabled && inputMethodManager.isActive(mMinuteSpinnerInput)) {
422 mMinuteSpinnerInput.clearFocus();
423 inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
424 }
425 }
427 private void updateSpinners() {
428 if (mDayEnabled) {
429 if (mCurrentDate.equals(mMinDate)) {
430 mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
431 mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
432 } else if (mCurrentDate.equals(mMaxDate)) {
433 mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
434 mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
435 } else {
436 mDaySpinner.setMinValue(1);
437 mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
438 }
439 mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
440 }
442 if (mWeekEnabled) {
443 mWeekSpinner.setMinValue(1);
444 mWeekSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.WEEK_OF_YEAR));
445 mWeekSpinner.setValue(mCurrentDate.get(Calendar.WEEK_OF_YEAR));
446 }
448 if (mMonthEnabled) {
449 mMonthSpinner.setDisplayedValues(null);
450 if (mCurrentDate.equals(mMinDate)) {
451 mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
452 mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
453 } else if (mCurrentDate.equals(mMaxDate)) {
454 mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
455 mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
456 } else {
457 mMonthSpinner.setMinValue(Calendar.JANUARY);
458 mMonthSpinner.setMaxValue(Calendar.DECEMBER);
459 }
461 String[] displayedValues = Arrays.copyOfRange(mShortMonths,
462 mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
463 mMonthSpinner.setDisplayedValues(displayedValues);
464 mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
465 }
467 if (mYearEnabled) {
468 mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
469 mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
470 mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
471 }
473 if (mHourEnabled) {
474 if (mIs12HourMode) {
475 mHourSpinner.setValue(mCurrentDate.get(Calendar.HOUR));
476 mAMPMSpinner.setValue(mCurrentDate.get(Calendar.AM_PM));
477 mAMPMSpinner.setDisplayedValues(mShortAMPMs);
478 } else {
479 mHourSpinner.setValue(mCurrentDate.get(Calendar.HOUR_OF_DAY));
480 }
481 }
482 if (mMinuteEnabled) {
483 mMinuteSpinner.setValue(mCurrentDate.get(Calendar.MINUTE));
484 }
485 }
487 private void updateCalendar() {
488 if (mCalendarEnabled){
489 mCalendar.setDate(mCurrentDate.getTimeInMillis(), false, false);
490 }
491 }
493 private void notifyDateChanged() {
494 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
495 }
497 public void toggleCalendar(boolean shown) {
498 if ((mState != PickersState.DATE && mState != PickersState.DATETIME) ||
499 Build.VERSION.SDK_INT < 11 || mScreenWidth < SCREEN_SIZE_THRESHOLD) {
500 if (DEBUG) Log.d(LOGTAG,"Cannot display calendar on this device, in this state" +
501 ": screen width :"+mScreenWidth);
502 return;
503 }
504 if (shown){
505 mCalendarEnabled = true;
506 mCalendar.setVisibility(VISIBLE);
507 setYearShown(false);
508 setWeekShown(false);
509 setMonthShown(false);
510 setDayShown(false);
511 } else {
512 mCalendar.setVisibility(GONE);
513 setYearShown(true);
514 setMonthShown(true);
515 setDayShown(true);
516 mSpinners.setOrientation(LinearLayout.HORIZONTAL);
517 mCalendarEnabled = false;
518 }
519 }
521 private void setYearShown(boolean shown) {
522 if (shown) {
523 toggleCalendar(false);
524 mYearSpinner.setVisibility(VISIBLE);
525 mYearEnabled = true;
526 } else {
527 mYearSpinner.setVisibility(GONE);
528 mYearEnabled = false;
529 }
530 }
532 private void setWeekShown(boolean shown) {
533 if (shown) {
534 toggleCalendar(false);
535 mWeekSpinner.setVisibility(VISIBLE);
536 mWeekEnabled = true;
537 } else {
538 mWeekSpinner.setVisibility(GONE);
539 mWeekEnabled = false;
540 }
541 }
543 private void setMonthShown(boolean shown) {
544 if (shown) {
545 toggleCalendar(false);
546 mMonthSpinner.setVisibility(VISIBLE);
547 mMonthEnabled = true;
548 } else {
549 mMonthSpinner.setVisibility(GONE);
550 mMonthEnabled = false;
551 }
552 }
554 private void setDayShown(boolean shown) {
555 if (shown) {
556 toggleCalendar(false);
557 mDaySpinner.setVisibility(VISIBLE);
558 mDayEnabled = true;
559 } else {
560 mDaySpinner.setVisibility(GONE);
561 mDayEnabled = false;
562 }
563 }
565 private void set12HourShown(boolean shown) {
566 if (shown) {
567 mAMPMSpinner.setVisibility(VISIBLE);
568 } else {
569 mAMPMSpinner.setVisibility(GONE);
570 }
571 }
573 private void setHourShown(boolean shown) {
574 if (shown) {
575 mHourSpinner.setVisibility(VISIBLE);
576 mHourEnabled= true;
577 } else {
578 mHourSpinner.setVisibility(GONE);
579 mAMPMSpinner.setVisibility(GONE);
580 mTimeSpinners.setVisibility(GONE);
581 mHourEnabled = false;
582 }
583 }
585 private void setMinuteShown(boolean shown) {
586 if (shown) {
587 mMinuteSpinner.setVisibility(VISIBLE);
588 mTimeSpinners.findViewById(R.id.mincolon).setVisibility(VISIBLE);
589 mMinuteEnabled= true;
590 } else {
591 mMinuteSpinner.setVisibility(GONE);
592 mTimeSpinners.findViewById(R.id.mincolon).setVisibility(GONE);
593 mMinuteEnabled = false;
594 }
595 }
597 private void setCurrentLocale(Locale locale) {
598 if (locale.equals(mCurrentLocale)) {
599 return;
600 }
602 mCurrentLocale = locale;
603 mIs12HourMode = !DateFormat.is24HourFormat(getContext());
604 mTempDate = getCalendarForLocale(mTempDate, locale);
605 mMinDate = getCalendarForLocale(mMinDate, locale);
606 mMaxDate = getCalendarForLocale(mMaxDate, locale);
607 mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
609 mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
611 mShortAMPMs = new String[2];
612 mShortAMPMs[0] = DateUtils.getAMPMString(Calendar.AM);
613 mShortAMPMs[1] = DateUtils.getAMPMString(Calendar.PM);
615 mShortMonths = new String[mNumberOfMonths];
616 for (int i = 0; i < mNumberOfMonths; i++) {
617 mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
618 DateUtils.LENGTH_MEDIUM);
619 }
620 }
622 private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
623 if (oldCalendar == null) {
624 return Calendar.getInstance(locale);
625 } else {
626 final long currentTimeMillis = oldCalendar.getTimeInMillis();
627 Calendar newCalendar = Calendar.getInstance(locale);
628 newCalendar.setTimeInMillis(currentTimeMillis);
629 return newCalendar;
630 }
631 }
633 public void updateDate(Calendar calendar) {
634 if (mCurrentDate.equals(calendar)) {
635 return;
636 }
637 mCurrentDate.setTimeInMillis(calendar.getTimeInMillis());
638 if (mCurrentDate.before(mMinDate)) {
639 mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
640 } else if (mCurrentDate.after(mMaxDate)) {
641 mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
642 }
643 updateSpinners();
644 notifyDateChanged();
645 }
647 }