1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/widget/DateTimePicker.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,648 @@ 1.4 +/* 1.5 + * Copyright (C) 2007 The Android Open Source Project 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +package org.mozilla.gecko.widget; 1.21 + 1.22 +import org.mozilla.gecko.R; 1.23 + 1.24 +import android.content.Context; 1.25 +import android.os.Build; 1.26 +import android.text.format.DateFormat; 1.27 +import android.text.format.DateUtils; 1.28 +import android.util.DisplayMetrics; 1.29 +import android.util.Log; 1.30 +import android.view.Display; 1.31 +import android.view.LayoutInflater; 1.32 +import android.view.WindowManager; 1.33 +import android.view.accessibility.AccessibilityEvent; 1.34 +import android.view.inputmethod.InputMethodManager; 1.35 +import android.widget.CalendarView; 1.36 +import android.widget.EditText; 1.37 +import android.widget.FrameLayout; 1.38 +import android.widget.LinearLayout; 1.39 +import android.widget.NumberPicker; 1.40 + 1.41 +import java.text.SimpleDateFormat; 1.42 +import java.util.Arrays; 1.43 +import java.util.Calendar; 1.44 +import java.util.Locale; 1.45 + 1.46 +public class DateTimePicker extends FrameLayout { 1.47 + 1.48 + private static final boolean DEBUG = true; 1.49 + private static final String LOGTAG = "GeckoDateTimePicker"; 1.50 + private static final String DATE_FORMAT = "MM/dd/yyyy"; 1.51 + private static final int DEFAULT_START_YEAR = 1; 1.52 + private static final int DEFAULT_END_YEAR = 9999; 1.53 + // Minimal screen width (in inches) for which we can show the calendar; 1.54 + private static final int SCREEN_SIZE_THRESHOLD = 5; 1.55 + private boolean mYearEnabled = true; 1.56 + private boolean mMonthEnabled = true; 1.57 + private boolean mWeekEnabled = false; 1.58 + private boolean mDayEnabled = true; 1.59 + private boolean mHourEnabled = true; 1.60 + private boolean mMinuteEnabled = true; 1.61 + private boolean mCalendarEnabled = false; 1.62 + private boolean mIs12HourMode; 1.63 + // Size of the screen in inches; 1.64 + private int mScreenWidth; 1.65 + private int mScreenHeight; 1.66 + private OnValueChangeListener mOnChangeListener; 1.67 + private final LinearLayout mPickers; 1.68 + private final LinearLayout mDateSpinners; 1.69 + private final LinearLayout mTimeSpinners; 1.70 + private final LinearLayout mSpinners; 1.71 + private final NumberPicker mDaySpinner; 1.72 + private final NumberPicker mMonthSpinner; 1.73 + private final NumberPicker mWeekSpinner; 1.74 + private final NumberPicker mYearSpinner; 1.75 + private final NumberPicker mHourSpinner; 1.76 + private final NumberPicker mMinuteSpinner; 1.77 + private final NumberPicker mAMPMSpinner; 1.78 + private final CalendarView mCalendar; 1.79 + private final EditText mDaySpinnerInput; 1.80 + private final EditText mMonthSpinnerInput; 1.81 + private final EditText mWeekSpinnerInput; 1.82 + private final EditText mYearSpinnerInput; 1.83 + private final EditText mHourSpinnerInput; 1.84 + private final EditText mMinuteSpinnerInput; 1.85 + private final EditText mAMPMSpinnerInput; 1.86 + private Locale mCurrentLocale; 1.87 + private String[] mShortMonths; 1.88 + private String[] mShortAMPMs; 1.89 + private int mNumberOfMonths; 1.90 + private Calendar mTempDate; 1.91 + private Calendar mMinDate; 1.92 + private Calendar mMaxDate; 1.93 + private Calendar mCurrentDate; 1.94 + private PickersState mState; 1.95 + 1.96 + public static enum PickersState { DATE, MONTH, WEEK, TIME, DATETIME }; 1.97 + 1.98 + public class OnValueChangeListener implements NumberPicker.OnValueChangeListener { 1.99 + @Override 1.100 + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { 1.101 + updateInputState(); 1.102 + mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis()); 1.103 + boolean newBehavior = (Build.VERSION.SDK_INT > 10); 1.104 + if (newBehavior) { 1.105 + if (DEBUG) Log.d(LOGTAG, "Sdk version > 10, using new behavior"); 1.106 + //The native date picker widget on these sdks increment 1.107 + //the next field when one field reach the maximum 1.108 + if (picker == mDaySpinner && mDayEnabled) { 1.109 + int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH); 1.110 + int old = mTempDate.get(Calendar.DAY_OF_MONTH); 1.111 + setTempDate(Calendar.DAY_OF_MONTH, old, newVal, 1, maxDayOfMonth); 1.112 + } else if (picker == mMonthSpinner && mMonthEnabled) { 1.113 + int old = mTempDate.get(Calendar.MONTH); 1.114 + setTempDate(Calendar.MONTH, old, newVal, Calendar.JANUARY, Calendar.DECEMBER); 1.115 + } else if (picker == mWeekSpinner) { 1.116 + int old = mTempDate.get(Calendar.WEEK_OF_YEAR); 1.117 + int maxWeekOfYear = mTempDate.getActualMaximum(Calendar.WEEK_OF_YEAR); 1.118 + setTempDate(Calendar.WEEK_OF_YEAR, old, newVal, 0, maxWeekOfYear); 1.119 + } else if (picker == mYearSpinner && mYearEnabled) { 1.120 + int month = mTempDate.get(Calendar.MONTH); 1.121 + mTempDate.set(Calendar.YEAR,newVal); 1.122 + // Changing the year shouldn't change the month. (in case of non-leap year a Feb 29) 1.123 + // change the day instead; 1.124 + if (month != mTempDate.get(Calendar.MONTH)){ 1.125 + mTempDate.set(Calendar.MONTH, month); 1.126 + mTempDate.set(Calendar.DAY_OF_MONTH, 1.127 + mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 1.128 + } 1.129 + } else if (picker == mHourSpinner && mHourEnabled) { 1.130 + if (mIs12HourMode) { 1.131 + setTempDate(Calendar.HOUR, oldVal, newVal, 1, 12); 1.132 + } else { 1.133 + setTempDate(Calendar.HOUR_OF_DAY, oldVal, newVal, 0, 23); 1.134 + } 1.135 + } else if (picker == mMinuteSpinner && mMinuteEnabled) { 1.136 + setTempDate(Calendar.MINUTE, oldVal, newVal, 0, 59); 1.137 + } else if (picker == mAMPMSpinner && mHourEnabled) { 1.138 + mTempDate.set(Calendar.AM_PM,newVal); 1.139 + } else { 1.140 + throw new IllegalArgumentException(); 1.141 + } 1.142 + } else { 1.143 + if (DEBUG) Log.d(LOGTAG,"Sdk version < 10, using old behavior"); 1.144 + if (picker == mDaySpinner && mDayEnabled){ 1.145 + mTempDate.set(Calendar.DAY_OF_MONTH, newVal); 1.146 + } else if (picker == mMonthSpinner && mMonthEnabled){ 1.147 + mTempDate.set(Calendar.MONTH, newVal); 1.148 + if (mTempDate.get(Calendar.MONTH) == newVal+1){ 1.149 + mTempDate.set(Calendar.MONTH, newVal); 1.150 + mTempDate.set(Calendar.DAY_OF_MONTH, 1.151 + mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 1.152 + } 1.153 + } else if (picker == mWeekSpinner){ 1.154 + mTempDate.set(Calendar.WEEK_OF_YEAR, newVal); 1.155 + } else if (picker == mYearSpinner && mYearEnabled){ 1.156 + int month = mTempDate.get(Calendar.MONTH); 1.157 + mTempDate.set(Calendar.YEAR, newVal); 1.158 + if (month != mTempDate.get(Calendar.MONTH)) { 1.159 + mTempDate.set(Calendar.MONTH, month); 1.160 + mTempDate.set(Calendar.DAY_OF_MONTH, 1.161 + mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 1.162 + } 1.163 + } else if (picker == mHourSpinner && mHourEnabled){ 1.164 + if (mIs12HourMode) { 1.165 + mTempDate.set(Calendar.HOUR, newVal); 1.166 + } else { 1.167 + mTempDate.set(Calendar.HOUR_OF_DAY, newVal); 1.168 + } 1.169 + } else if (picker == mMinuteSpinner && mMinuteEnabled){ 1.170 + mTempDate.set(Calendar.MINUTE, newVal); 1.171 + } else if (picker == mAMPMSpinner && mHourEnabled) { 1.172 + mTempDate.set(Calendar.AM_PM, newVal); 1.173 + } else { 1.174 + throw new IllegalArgumentException(); 1.175 + } 1.176 + } 1.177 + setDate(mTempDate); 1.178 + if (mDayEnabled) { 1.179 + mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 1.180 + } 1.181 + if(mWeekEnabled) { 1.182 + mWeekSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.WEEK_OF_YEAR)); 1.183 + } 1.184 + updateCalendar(); 1.185 + updateSpinners(); 1.186 + notifyDateChanged(); 1.187 + } 1.188 + 1.189 + private void setTempDate(int field, int oldVal, int newVal, int min, int max) { 1.190 + if (oldVal == max && newVal == min ) { 1.191 + mTempDate.add(field, 1); 1.192 + } else if (oldVal == min && newVal == max) { 1.193 + mTempDate.add(field, -1); 1.194 + } else { 1.195 + mTempDate.add(field, newVal - oldVal); 1.196 + } 1.197 + } 1.198 + } 1.199 + 1.200 + private static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() { 1.201 + final StringBuilder mBuilder = new StringBuilder(); 1.202 + 1.203 + final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US); 1.204 + 1.205 + final Object[] mArgs = new Object[1]; 1.206 + 1.207 + @Override 1.208 + public String format(int value) { 1.209 + mArgs[0] = value; 1.210 + mBuilder.delete(0, mBuilder.length()); 1.211 + mFmt.format("%02d", mArgs); 1.212 + return mFmt.toString(); 1.213 + } 1.214 + }; 1.215 + 1.216 + private void displayPickers() { 1.217 + setWeekShown(false); 1.218 + set12HourShown(mIs12HourMode); 1.219 + if (mState == PickersState.DATETIME) { 1.220 + return; 1.221 + } 1.222 + setHourShown(false); 1.223 + setMinuteShown(false); 1.224 + if (mState == PickersState.WEEK) { 1.225 + setDayShown(false); 1.226 + setMonthShown(false); 1.227 + setWeekShown(true); 1.228 + } else if (mState == PickersState.MONTH) { 1.229 + setDayShown(false); 1.230 + } 1.231 + } 1.232 + 1.233 + public DateTimePicker(Context context) { 1.234 + this(context, "", "", PickersState.DATE); 1.235 + } 1.236 + 1.237 + public DateTimePicker(Context context, String dateFormat, String dateTimeValue, PickersState state) { 1.238 + super(context); 1.239 + if (Build.VERSION.SDK_INT < 11) { 1.240 + throw new UnsupportedOperationException("Custom DateTimePicker is only available for SDK > 10"); 1.241 + } 1.242 + setCurrentLocale(Locale.getDefault()); 1.243 + mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1); 1.244 + mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31); 1.245 + mState = state; 1.246 + LayoutInflater inflater = LayoutInflater.from(context); 1.247 + inflater.inflate(R.layout.datetime_picker, this, true); 1.248 + 1.249 + mOnChangeListener = new OnValueChangeListener(); 1.250 + 1.251 + mDateSpinners = (LinearLayout)findViewById(R.id.date_spinners); 1.252 + mTimeSpinners = (LinearLayout)findViewById(R.id.time_spinners); 1.253 + mSpinners = (LinearLayout)findViewById(R.id.spinners); 1.254 + mPickers = (LinearLayout)findViewById(R.id.datetime_picker); 1.255 + 1.256 + // We will display differently according to the screen size width. 1.257 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 1.258 + Display display = wm.getDefaultDisplay(); 1.259 + DisplayMetrics dm = new DisplayMetrics(); 1.260 + display.getMetrics(dm); 1.261 + mScreenWidth = display.getWidth() / dm.densityDpi; 1.262 + mScreenHeight = display.getHeight() / dm.densityDpi; 1.263 + if (DEBUG) Log.d(LOGTAG, "screen width: " + mScreenWidth + " screen height: " + mScreenHeight); 1.264 + 1.265 + // If we're displaying a date, the screen is wide enought (and if we're using a sdk where the calendar view exists) 1.266 + // then display a calendar. 1.267 + if ((mState == PickersState.DATE || mState == PickersState.DATETIME) && 1.268 + Build.VERSION.SDK_INT > 10 && mScreenWidth >= SCREEN_SIZE_THRESHOLD) { 1.269 + if (DEBUG) Log.d(LOGTAG,"SDK > 10 and screen wide enough, displaying calendar"); 1.270 + mCalendar = new CalendarView(context); 1.271 + mCalendar.setVisibility(GONE); 1.272 + 1.273 + LayoutParams layoutParams = new LayoutParams(250,280); 1.274 + mCalendar.setLayoutParams(layoutParams); 1.275 + mCalendar.setFocusable(true); 1.276 + mCalendar.setFocusableInTouchMode(true); 1.277 + mCalendar.setMaxDate(mMaxDate.getTimeInMillis()); 1.278 + mCalendar.setMinDate(mMinDate.getTimeInMillis()); 1.279 + 1.280 + mCalendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() { 1.281 + @Override 1.282 + public void onSelectedDayChange( 1.283 + CalendarView view, int year, int month, int monthDay) { 1.284 + mTempDate.set(year, month, monthDay); 1.285 + setDate(mTempDate); 1.286 + notifyDateChanged(); 1.287 + } 1.288 + }); 1.289 + 1.290 + mPickers.addView(mCalendar); 1.291 + } else { 1.292 + // If the screen is more wide than high, we are displaying daye and time spinners, 1.293 + // and if there is no calendar displayed, 1.294 + // we should display the fields in one row. 1.295 + if (mScreenWidth > mScreenHeight && mState == PickersState.DATETIME) { 1.296 + mSpinners.setOrientation(LinearLayout.HORIZONTAL); 1.297 + } 1.298 + mCalendar = null; 1.299 + } 1.300 + 1.301 + // Find the initial date from the constructor arguments. 1.302 + try { 1.303 + if (!dateTimeValue.equals("")) { 1.304 + mTempDate.setTime(new SimpleDateFormat(dateFormat).parse(dateTimeValue)); 1.305 + } else { 1.306 + mTempDate.setTimeInMillis(System.currentTimeMillis()); 1.307 + } 1.308 + } catch (Exception ex) { 1.309 + Log.e(LOGTAG, "Error parsing format string: " + ex); 1.310 + mTempDate.setTimeInMillis(System.currentTimeMillis()); 1.311 + } 1.312 + 1.313 + // Initialize all spinners. 1.314 + mDaySpinner = setupSpinner(R.id.day, 1, 1.315 + mTempDate.get(Calendar.DAY_OF_MONTH)); 1.316 + mDaySpinner.setFormatter(TWO_DIGIT_FORMATTER); 1.317 + mDaySpinnerInput = (EditText) mDaySpinner.getChildAt(1); 1.318 + 1.319 + mMonthSpinner = setupSpinner(R.id.month, 1, 1.320 + mTempDate.get(Calendar.MONTH)); 1.321 + mMonthSpinner.setFormatter(TWO_DIGIT_FORMATTER); 1.322 + mMonthSpinner.setDisplayedValues(mShortMonths); 1.323 + mMonthSpinnerInput = (EditText) mMonthSpinner.getChildAt(1); 1.324 + 1.325 + mWeekSpinner = setupSpinner(R.id.week, 1, 1.326 + mTempDate.get(Calendar.WEEK_OF_YEAR)); 1.327 + mWeekSpinner.setFormatter(TWO_DIGIT_FORMATTER); 1.328 + mWeekSpinnerInput = (EditText) mWeekSpinner.getChildAt(1); 1.329 + 1.330 + mYearSpinner = setupSpinner(R.id.year, DEFAULT_START_YEAR, 1.331 + DEFAULT_END_YEAR); 1.332 + mYearSpinnerInput = (EditText) mYearSpinner.getChildAt(1); 1.333 + 1.334 + mAMPMSpinner = setupSpinner(R.id.ampm, 0, 1); 1.335 + mAMPMSpinner.setFormatter(TWO_DIGIT_FORMATTER); 1.336 + 1.337 + if (mIs12HourMode) { 1.338 + mHourSpinner = setupSpinner(R.id.hour, 1, 12); 1.339 + mAMPMSpinnerInput = (EditText) mAMPMSpinner.getChildAt(1); 1.340 + mAMPMSpinner.setDisplayedValues(mShortAMPMs); 1.341 + } else { 1.342 + mHourSpinner = setupSpinner(R.id.hour, 0, 23); 1.343 + mAMPMSpinnerInput = null; 1.344 + } 1.345 + 1.346 + mHourSpinner.setFormatter(TWO_DIGIT_FORMATTER); 1.347 + mHourSpinnerInput = (EditText) mHourSpinner.getChildAt(1); 1.348 + 1.349 + mMinuteSpinner = setupSpinner(R.id.minute, 0, 59); 1.350 + mMinuteSpinner.setFormatter(TWO_DIGIT_FORMATTER); 1.351 + mMinuteSpinnerInput = (EditText) mMinuteSpinner.getChildAt(1); 1.352 + 1.353 + // The order in which the spinners are displayed are locale-dependent 1.354 + reorderDateSpinners(); 1.355 + // Set the date to the initial date. Since this date can come from the user, 1.356 + // it can fire an exception (out-of-bound date) 1.357 + try { 1.358 + updateDate(mTempDate); 1.359 + } catch (Exception ex) { } 1.360 + 1.361 + // Display only the pickers needed for the current state. 1.362 + displayPickers(); 1.363 + } 1.364 + 1.365 + public NumberPicker setupSpinner(int id, int min, int max) { 1.366 + NumberPicker mSpinner = (NumberPicker) findViewById(id); 1.367 + mSpinner.setMinValue(min); 1.368 + mSpinner.setMaxValue(max); 1.369 + mSpinner.setOnValueChangedListener(mOnChangeListener); 1.370 + mSpinner.setOnLongPressUpdateInterval(100); 1.371 + return mSpinner; 1.372 + } 1.373 + 1.374 + public long getTimeInMillis(){ 1.375 + return mCurrentDate.getTimeInMillis(); 1.376 + } 1.377 + 1.378 + private void reorderDateSpinners() { 1.379 + mDateSpinners.removeAllViews(); 1.380 + char[] order = DateFormat.getDateFormatOrder(getContext()); 1.381 + final int spinnerCount = order.length; 1.382 + for (int i = 0; i < spinnerCount; i++) { 1.383 + switch (order[i]) { 1.384 + case DateFormat.DATE: 1.385 + mDateSpinners.addView(mDaySpinner); 1.386 + break; 1.387 + case DateFormat.MONTH: 1.388 + mDateSpinners.addView(mMonthSpinner); 1.389 + break; 1.390 + case DateFormat.YEAR: 1.391 + mDateSpinners.addView(mYearSpinner); 1.392 + break; 1.393 + default: 1.394 + throw new IllegalArgumentException(); 1.395 + } 1.396 + } 1.397 + mDateSpinners.addView(mWeekSpinner); 1.398 + } 1.399 + 1.400 + private void setDate(Calendar calendar){ 1.401 + mCurrentDate = mTempDate; 1.402 + if (mCurrentDate.before(mMinDate)) { 1.403 + mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); 1.404 + } else if (mCurrentDate.after(mMaxDate)) { 1.405 + mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); 1.406 + } 1.407 + } 1.408 + 1.409 + private void updateInputState() { 1.410 + InputMethodManager inputMethodManager = (InputMethodManager) 1.411 + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 1.412 + if (mYearEnabled && inputMethodManager.isActive(mYearSpinnerInput)) { 1.413 + mYearSpinnerInput.clearFocus(); 1.414 + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 1.415 + } else if (mMonthEnabled && inputMethodManager.isActive(mMonthSpinnerInput)) { 1.416 + mMonthSpinnerInput.clearFocus(); 1.417 + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 1.418 + } else if (mDayEnabled && inputMethodManager.isActive(mDaySpinnerInput)) { 1.419 + mDaySpinnerInput.clearFocus(); 1.420 + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 1.421 + } else if (mHourEnabled && inputMethodManager.isActive(mHourSpinnerInput)) { 1.422 + mHourSpinnerInput.clearFocus(); 1.423 + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 1.424 + } else if (mMinuteEnabled && inputMethodManager.isActive(mMinuteSpinnerInput)) { 1.425 + mMinuteSpinnerInput.clearFocus(); 1.426 + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 1.427 + } 1.428 + } 1.429 + 1.430 + private void updateSpinners() { 1.431 + if (mDayEnabled) { 1.432 + if (mCurrentDate.equals(mMinDate)) { 1.433 + mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); 1.434 + mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 1.435 + } else if (mCurrentDate.equals(mMaxDate)) { 1.436 + mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH)); 1.437 + mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); 1.438 + } else { 1.439 + mDaySpinner.setMinValue(1); 1.440 + mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 1.441 + } 1.442 + mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); 1.443 + } 1.444 + 1.445 + if (mWeekEnabled) { 1.446 + mWeekSpinner.setMinValue(1); 1.447 + mWeekSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.WEEK_OF_YEAR)); 1.448 + mWeekSpinner.setValue(mCurrentDate.get(Calendar.WEEK_OF_YEAR)); 1.449 + } 1.450 + 1.451 + if (mMonthEnabled) { 1.452 + mMonthSpinner.setDisplayedValues(null); 1.453 + if (mCurrentDate.equals(mMinDate)) { 1.454 + mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH)); 1.455 + mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH)); 1.456 + } else if (mCurrentDate.equals(mMaxDate)) { 1.457 + mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH)); 1.458 + mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH)); 1.459 + } else { 1.460 + mMonthSpinner.setMinValue(Calendar.JANUARY); 1.461 + mMonthSpinner.setMaxValue(Calendar.DECEMBER); 1.462 + } 1.463 + 1.464 + String[] displayedValues = Arrays.copyOfRange(mShortMonths, 1.465 + mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1); 1.466 + mMonthSpinner.setDisplayedValues(displayedValues); 1.467 + mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH)); 1.468 + } 1.469 + 1.470 + if (mYearEnabled) { 1.471 + mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR)); 1.472 + mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR)); 1.473 + mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR)); 1.474 + } 1.475 + 1.476 + if (mHourEnabled) { 1.477 + if (mIs12HourMode) { 1.478 + mHourSpinner.setValue(mCurrentDate.get(Calendar.HOUR)); 1.479 + mAMPMSpinner.setValue(mCurrentDate.get(Calendar.AM_PM)); 1.480 + mAMPMSpinner.setDisplayedValues(mShortAMPMs); 1.481 + } else { 1.482 + mHourSpinner.setValue(mCurrentDate.get(Calendar.HOUR_OF_DAY)); 1.483 + } 1.484 + } 1.485 + if (mMinuteEnabled) { 1.486 + mMinuteSpinner.setValue(mCurrentDate.get(Calendar.MINUTE)); 1.487 + } 1.488 + } 1.489 + 1.490 + private void updateCalendar() { 1.491 + if (mCalendarEnabled){ 1.492 + mCalendar.setDate(mCurrentDate.getTimeInMillis(), false, false); 1.493 + } 1.494 + } 1.495 + 1.496 + private void notifyDateChanged() { 1.497 + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 1.498 + } 1.499 + 1.500 + public void toggleCalendar(boolean shown) { 1.501 + if ((mState != PickersState.DATE && mState != PickersState.DATETIME) || 1.502 + Build.VERSION.SDK_INT < 11 || mScreenWidth < SCREEN_SIZE_THRESHOLD) { 1.503 + if (DEBUG) Log.d(LOGTAG,"Cannot display calendar on this device, in this state" + 1.504 + ": screen width :"+mScreenWidth); 1.505 + return; 1.506 + } 1.507 + if (shown){ 1.508 + mCalendarEnabled = true; 1.509 + mCalendar.setVisibility(VISIBLE); 1.510 + setYearShown(false); 1.511 + setWeekShown(false); 1.512 + setMonthShown(false); 1.513 + setDayShown(false); 1.514 + } else { 1.515 + mCalendar.setVisibility(GONE); 1.516 + setYearShown(true); 1.517 + setMonthShown(true); 1.518 + setDayShown(true); 1.519 + mSpinners.setOrientation(LinearLayout.HORIZONTAL); 1.520 + mCalendarEnabled = false; 1.521 + } 1.522 + } 1.523 + 1.524 + private void setYearShown(boolean shown) { 1.525 + if (shown) { 1.526 + toggleCalendar(false); 1.527 + mYearSpinner.setVisibility(VISIBLE); 1.528 + mYearEnabled = true; 1.529 + } else { 1.530 + mYearSpinner.setVisibility(GONE); 1.531 + mYearEnabled = false; 1.532 + } 1.533 + } 1.534 + 1.535 + private void setWeekShown(boolean shown) { 1.536 + if (shown) { 1.537 + toggleCalendar(false); 1.538 + mWeekSpinner.setVisibility(VISIBLE); 1.539 + mWeekEnabled = true; 1.540 + } else { 1.541 + mWeekSpinner.setVisibility(GONE); 1.542 + mWeekEnabled = false; 1.543 + } 1.544 + } 1.545 + 1.546 + private void setMonthShown(boolean shown) { 1.547 + if (shown) { 1.548 + toggleCalendar(false); 1.549 + mMonthSpinner.setVisibility(VISIBLE); 1.550 + mMonthEnabled = true; 1.551 + } else { 1.552 + mMonthSpinner.setVisibility(GONE); 1.553 + mMonthEnabled = false; 1.554 + } 1.555 + } 1.556 + 1.557 + private void setDayShown(boolean shown) { 1.558 + if (shown) { 1.559 + toggleCalendar(false); 1.560 + mDaySpinner.setVisibility(VISIBLE); 1.561 + mDayEnabled = true; 1.562 + } else { 1.563 + mDaySpinner.setVisibility(GONE); 1.564 + mDayEnabled = false; 1.565 + } 1.566 + } 1.567 + 1.568 + private void set12HourShown(boolean shown) { 1.569 + if (shown) { 1.570 + mAMPMSpinner.setVisibility(VISIBLE); 1.571 + } else { 1.572 + mAMPMSpinner.setVisibility(GONE); 1.573 + } 1.574 + } 1.575 + 1.576 + private void setHourShown(boolean shown) { 1.577 + if (shown) { 1.578 + mHourSpinner.setVisibility(VISIBLE); 1.579 + mHourEnabled= true; 1.580 + } else { 1.581 + mHourSpinner.setVisibility(GONE); 1.582 + mAMPMSpinner.setVisibility(GONE); 1.583 + mTimeSpinners.setVisibility(GONE); 1.584 + mHourEnabled = false; 1.585 + } 1.586 + } 1.587 + 1.588 + private void setMinuteShown(boolean shown) { 1.589 + if (shown) { 1.590 + mMinuteSpinner.setVisibility(VISIBLE); 1.591 + mTimeSpinners.findViewById(R.id.mincolon).setVisibility(VISIBLE); 1.592 + mMinuteEnabled= true; 1.593 + } else { 1.594 + mMinuteSpinner.setVisibility(GONE); 1.595 + mTimeSpinners.findViewById(R.id.mincolon).setVisibility(GONE); 1.596 + mMinuteEnabled = false; 1.597 + } 1.598 + } 1.599 + 1.600 + private void setCurrentLocale(Locale locale) { 1.601 + if (locale.equals(mCurrentLocale)) { 1.602 + return; 1.603 + } 1.604 + 1.605 + mCurrentLocale = locale; 1.606 + mIs12HourMode = !DateFormat.is24HourFormat(getContext()); 1.607 + mTempDate = getCalendarForLocale(mTempDate, locale); 1.608 + mMinDate = getCalendarForLocale(mMinDate, locale); 1.609 + mMaxDate = getCalendarForLocale(mMaxDate, locale); 1.610 + mCurrentDate = getCalendarForLocale(mCurrentDate, locale); 1.611 + 1.612 + mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1; 1.613 + 1.614 + mShortAMPMs = new String[2]; 1.615 + mShortAMPMs[0] = DateUtils.getAMPMString(Calendar.AM); 1.616 + mShortAMPMs[1] = DateUtils.getAMPMString(Calendar.PM); 1.617 + 1.618 + mShortMonths = new String[mNumberOfMonths]; 1.619 + for (int i = 0; i < mNumberOfMonths; i++) { 1.620 + mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i, 1.621 + DateUtils.LENGTH_MEDIUM); 1.622 + } 1.623 + } 1.624 + 1.625 + private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) { 1.626 + if (oldCalendar == null) { 1.627 + return Calendar.getInstance(locale); 1.628 + } else { 1.629 + final long currentTimeMillis = oldCalendar.getTimeInMillis(); 1.630 + Calendar newCalendar = Calendar.getInstance(locale); 1.631 + newCalendar.setTimeInMillis(currentTimeMillis); 1.632 + return newCalendar; 1.633 + } 1.634 + } 1.635 + 1.636 + public void updateDate(Calendar calendar) { 1.637 + if (mCurrentDate.equals(calendar)) { 1.638 + return; 1.639 + } 1.640 + mCurrentDate.setTimeInMillis(calendar.getTimeInMillis()); 1.641 + if (mCurrentDate.before(mMinDate)) { 1.642 + mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); 1.643 + } else if (mCurrentDate.after(mMaxDate)) { 1.644 + mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); 1.645 + } 1.646 + updateSpinners(); 1.647 + notifyDateChanged(); 1.648 + } 1.649 + 1.650 +} 1.651 +