content: /*
   * Copyright (C) 2016 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 android.widget;
  
  import android.annotation.UnsupportedAppUsage;
  import android.content.Context;
  import android.content.res.Configuration;
  import android.content.res.TypedArray;
  import android.icu.util.Calendar;
  import android.os.Parcelable;
  import android.text.InputType;
  import android.text.TextUtils;
  import android.text.format.DateFormat;
  import android.util.AttributeSet;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.accessibility.AccessibilityEvent;
  import android.view.inputmethod.EditorInfo;
  import android.view.inputmethod.InputMethodManager;
  import android.widget.DatePicker.AbstractDatePickerDelegate;
  import android.widget.NumberPicker.OnValueChangeListener;
  
  import libcore.icu.ICU;
  
  import java.text.DateFormatSymbols;
  import java.text.ParseException;
  import java.text.SimpleDateFormat;
  import java.util.Arrays;
  import java.util.Locale;
  
  /**
   * A delegate implementing the basic DatePicker
   */
  class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
  
      private static final String DATE_FORMAT = "MM/dd/yyyy";
  
      private static final int DEFAULT_START_YEAR = 1900;
  
      private static final int DEFAULT_END_YEAR = 2100;
  
      private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
  
      private static final boolean DEFAULT_SPINNERS_SHOWN = true;
  
      private static final boolean DEFAULT_ENABLED_STATE = true;
  
      private final LinearLayout mSpinners;
  
      private final NumberPicker mDaySpinner;
  
      private final NumberPicker mMonthSpinner;
  
      private final NumberPicker mYearSpinner;
  
      private final EditText mDaySpinnerInput;
  
      private final EditText mMonthSpinnerInput;
  
      private final EditText mYearSpinnerInput;
  
      private final CalendarView mCalendarView;
  
      private String[] mShortMonths;
  
      private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
  
      private int mNumberOfMonths;
  
      private Calendar mTempDate;
  
      private Calendar mMinDate;
  
      private Calendar mMaxDate;
  
      private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
  
      DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
              int defStyleAttr, int defStyleRes) {
          super(delegator, context);
  
          mDelegator = delegator;
          mContext = context;
  
          // initialization based on locale
          setCurrentLocale(Locale.getDefault());
  
          final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
                  com.android.internal.R.styleable.DatePicker, defStyleAttr, defStyleRes);
          boolean spinnersShown = attributesArray.getBoolean(com.android.internal.R.styleable.DatePicker_spinnersShown,
                  DEFAULT_SPINNERS_SHOWN);
          boolean calendarViewShown = attributesArray.getBoolean(
                  com.android.internal.R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
          int startYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_startYear,
                  DEFAULT_START_YEAR);
          int endYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
          String minDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_minDate);
          String maxDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_maxDate);
          int layoutResourceId = attributesArray.getResourceId(
                  com.android.internal.R.styleable.DatePicker_legacyLayout, com.android.internal.R.layout.date_picker_legacy);
          attributesArray.recycle();
  
          LayoutInflater inflater = (LayoutInflater) context
                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          final View view = inflater.inflate(layoutResourceId, mDelegator, true);
          view.setSaveFromParentEnabled(false);
  
          OnValueChangeListener onChangeListener = new OnValueChangeListener() {
              public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                  updateInputState();
                  mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
                  // take care of wrapping of days and months to update greater fields
                  if (picker == mDaySpinner) {
                      int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
                      if (oldVal == maxDayOfMonth && newVal == 1) {
                          mTempDate.add(Calendar.DAY_OF_MONTH, 1);
                      } else if (oldVal == 1 && newVal == maxDayOfMonth) {
                          mTempDate.add(Calendar.DAY_OF_MONTH, -1);
                      } else {
                          mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
                      }
                  } else if (picker == mMonthSpinner) {
                      if (oldVal == 11 && newVal == 0) {
                          mTempDate.add(Calendar.MONTH, 1);
                      } else if (oldVal == 0 && newVal == 11) {
                          mTempDate.add(Calendar.MONTH, -1);
                      } else {
                          mTempDate.add(Calendar.MONTH, newVal - oldVal);
                      }
                  } else if (picker == mYearSpinner) {
                      mTempDate.set(Calendar.YEAR, newVal);
                  } else {
                      throw new IllegalArgumentException();
                  }
                  // now set the date to the adjusted one
                  setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
                          mTempDate.get(Calendar.DAY_OF_MONTH));
                  updateSpinners();
                  updateCalendarView();
                  notifyDateChanged();
              }
          };
  
          mSpinners = (LinearLayout) mDelegator.findViewById(com.android.internal.R.id.pickers);
  
          // calendar view day-picker
          mCalendarView = (CalendarView) mDelegator.findViewById(com.android.internal.R.id.calendar_view);
          mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
              public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
                  setDate(year, month, monthDay);
                  updateSpinners();
                  notifyDateChanged();
              }
          });
  
          // day
          mDaySpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.day);
          mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
          mDaySpinner.setOnLongPressUpdateInterval(100);
          mDaySpinner.setOnValueChangedListener(onChangeListener);
          mDaySpinnerInput = (EditText) mDaySpinner.findViewById(com.android.internal.R.id.numberpicker_input);
  
          // month
          mMonthSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.month);
          mMonthSpinner.setMinValue(0);
          mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
          mMonthSpinner.setDisplayedValues(mShortMonths);
          mMonthSpinner.setOnLongPressUpdateInterval(200);
          mMonthSpinner.setOnValueChangedListener(onChangeListener);
          mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
  
          // year
          mYearSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.year);
          mYearSpinner.setOnLongPressUpdateInterval(100);
          mYearSpinner.setOnValueChangedListener(onChangeListener);
          mYearSpinnerInput = (EditText) mYearSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
  
          // show only what the user required but make sure we
          // show something and the spinners have higher priority
          if (!spinnersShown && !calendarViewShown) {
              setSpinnersShown(true);
          } else {
              setSpinnersShown(spinnersShown);
              setCalendarViewShown(calendarViewShown);
          }
  
          // set the min date giving priority of the minDate over startYear
          mTempDate.clear();
          if (!TextUtils.isEmpty(minDate)) {
              if (!parseDate(minDate, mTempDate)) {
                  mTempDate.set(startYear, 0, 1);
              }
          } else {
              mTempDate.set(startYear, 0, 1);
          }
          setMinDate(mTempDate.getTimeInMillis());
  
          // set the max date giving priority of the maxDate over endYear
          mTempDate.clear();
          if (!TextUtils.isEmpty(maxDate)) {
              if (!parseDate(maxDate, mTempDate)) {
                  mTempDate.set(endYear, 11, 31);
              }
          } else {
              mTempDate.set(endYear, 11, 31);
          }
          setMaxDate(mTempDate.getTimeInMillis());
  
          // initialize to current date
          mCurrentDate.setTimeInMillis(System.currentTimeMillis());
          init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
                  .get(Calendar.DAY_OF_MONTH), null);
  
          // re-order the number spinners to match the current date format
          reorderSpinners();
  
          // accessibility
          setContentDescriptions();
  
          // If not explicitly specified this view is important for accessibility.
          if (mDelegator.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
              mDelegator.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
          }
      }
  
      @Override
      public void init(int year, int monthOfYear, int dayOfMonth,
                       DatePicker.OnDateChangedListener onDateChangedListener) {
          setDate(year, monthOfYear, dayOfMonth);
          updateSpinners();
          updateCalendarView();
  
          mOnDateChangedListener = onDateChangedListener;
      }
  
      @Override
      public void updateDate(int year, int month, int dayOfMonth) {
          if (!isNewDate(year, month, dayOfMonth)) {
              return;
          }
          setDate(year, month, dayOfMonth);
          updateSpinners();
          updateCalendarView();
          notifyDateChanged();
      }
  
      @Override
      public int getYear() {
          return mCurrentDate.get(Calendar.YEAR);
      }
  
      @Override
      public int getMonth() {
          return mCurrentDate.get(Calendar.MONTH);
      }
  
      @Override
      public int getDayOfMonth() {
          return mCurrentDate.get(Calendar.DAY_OF_MONTH);
      }
  
      @Override
      public void setFirstDayOfWeek(int firstDayOfWeek) {
          mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
      }
  
      @Override
      public int getFirstDayOfWeek() {
          return mCalendarView.getFirstDayOfWeek();
      }
  
      @Override
      public void setMinDate(long minDate) {
          mTempDate.setTimeInMillis(minDate);
          if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
                  && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) {
              // Same day, no-op.
              return;
          }
          mMinDate.setTimeInMillis(minDate);
          mCalendarView.setMinDate(minDate);
          if (mCurrentDate.before(mMinDate)) {
              mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
              updateCalendarView();
          }
          updateSpinners();
      }
  
      @Override
      public Calendar getMinDate() {
          final Calendar minDate = Calendar.getInstance();
          minDate.setTimeInMillis(mCalendarView.getMinDate());
          return minDate;
      }
  
      @Override
      public void setMaxDate(long maxDate) {
          mTempDate.setTimeInMillis(maxDate);
          if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
                  && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) {
              // Same day, no-op.
              return;
          }
          mMaxDate.setTimeInMillis(maxDate);
          mCalendarView.setMaxDate(maxDate);
          if (mCurrentDate.after(mMaxDate)) {
              mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
              updateCalendarView();
          }
          updateSpinners();
      }
  
      @Override
      public Calendar getMaxDate() {
          final Calendar maxDate = Calendar.getInstance();
          maxDate.setTimeInMillis(mCalendarView.getMaxDate());
          return maxDate;
      }
  
      @Override
      public void setEnabled(boolean enabled) {
          mDaySpinner.setEnabled(enabled);
          mMonthSpinner.setEnabled(enabled);
          mYearSpinner.setEnabled(enabled);
          mCalendarView.setEnabled(enabled);
          mIsEnabled = enabled;
      }
  
      @Override
      public boolean isEnabled() {
          return mIsEnabled;
      }
  
      @Override
      public CalendarView getCalendarView() {
          return mCalendarView;
      }
  
      @Override
      public void setCalendarViewShown(boolean shown) {
          mCalendarView.setVisibility(shown ? View.VISIBLE : View.GONE);
      }
  
      @Override
      public boolean getCalendarViewShown() {
          return (mCalendarView.getVisibility() == View.VISIBLE);
      }
  
      @Override
      public void setSpinnersShown(boolean shown) {
          mSpinners.setVisibility(shown ? View.VISIBLE : View.GONE);
      }
  
      @Override
      public boolean getSpinnersShown() {
          return mSpinners.isShown();
      }
  
      @Override
      public void onConfigurationChanged(Configuration newConfig) {
          setCurrentLocale(newConfig.locale);
      }
  
      @Override
      public Parcelable onSaveInstanceState(Parcelable superState) {
          return new SavedState(superState, getYear(), getMonth(), getDayOfMonth(),
                  getMinDate().getTimeInMillis(), getMaxDate().getTimeInMillis());
      }
  
      @Override
      public void onRestoreInstanceState(Parcelable state) {
          if (state instanceof SavedState) {
              final SavedState ss = (SavedState) state;
              setDate(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
              updateSpinners();
              updateCalendarView();
          }
      }
  
      @Override
      public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
          onPopulateAccessibilityEvent(event);
          return true;
      }
  
      /**
       * Sets the current locale.
       *
       * @param locale The current locale.
       */
      @Override
      protected void setCurrentLocale(Locale locale) {
          super.setCurrentLocale(locale);
  
          mTempDate = getCalendarForLocale(mTempDate, locale);
          mMinDate = getCalendarForLocale(mMinDate, locale);
          mMaxDate = getCalendarForLocale(mMaxDate, locale);
          mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
  
          mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
          mShortMonths = new DateFormatSymbols().getShortMonths();
  
          if (usingNumericMonths()) {
              // We're in a locale where a date should either be all-numeric, or all-text.
              // All-text would require custom NumberPicker formatters for day and year.
              mShortMonths = new String[mNumberOfMonths];
              for (int i = 0; i < mNumberOfMonths; ++i) {
                  mShortMonths[i] = String.format("%d", i + 1);
              }
          }
      }
  
      /**
       * Tests whether the current locale is one where there are no real month names,
       * such as Chinese, Japanese, or Korean locales.
       */
      private boolean usingNumericMonths() {
          return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
      }
  
      /**
       * Gets a calendar for locale bootstrapped with the value of a given calendar.
       *
       * @param oldCalendar The old calendar.
       * @param locale The locale.
       */
      private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
          if (oldCalendar == null) {
              return Calendar.getInstance(locale);
          } else {
              final long currentTimeMillis = oldCalendar.getTimeInMillis();
              Calendar newCalendar = Calendar.getInstance(locale);
              newCalendar.setTimeInMillis(currentTimeMillis);
              return newCalendar;
          }
      }
  
      /**
       * Reorders the spinners according to the date format that is
       * explicitly set by the user and if no such is set fall back
       * to the current locale's default format.
       */
      private void reorderSpinners() {
          mSpinners.removeAllViews();
          // We use numeric spinners for year and day, but textual months. Ask icu4c what
          // order the user's locale uses for that combination. http://b/7207103.
          String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
          char[] order = ICU.getDateFormatOrder(pattern);
          final int spinnerCount = order.length;
          for (int i = 0; i < spinnerCount; i++) {
              switch (order[i]) {
                  case 'd':
                      mSpinners.addView(mDaySpinner);
                      setImeOptions(mDaySpinner, spinnerCount, i);
                      break;
                  case 'M':
                      mSpinners.addView(mMonthSpinner);
                      setImeOptions(mMonthSpinner, spinnerCount, i);
                      break;
                  case 'y':
                      mSpinners.addView(mYearSpinner);
                      setImeOptions(mYearSpinner, spinnerCount, i);
                      break;
                  default:
                      throw new IllegalArgumentException(Arrays.toString(order));
              }
          }
      }
  
      /**
       * Parses the given <code>date</code> and in case of success sets the result
       * to the <code>outDate</code>.
       *
       * @return True if the date was parsed.
       */
      private boolean parseDate(String date, Calendar outDate) {
          try {
              outDate.setTime(mDateFormat.parse(date));
              return true;
          } catch (ParseException e) {
              e.printStackTrace();
              return false;
          }
      }
  
      private boolean isNewDate(int year, int month, int dayOfMonth) {
          return (mCurrentDate.get(Calendar.YEAR) != year
                  || mCurrentDate.get(Calendar.MONTH) != month
                  || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
      }
  
      @UnsupportedAppUsage
      private void setDate(int year, int month, int dayOfMonth) {
          mCurrentDate.set(year, month, dayOfMonth);
          resetAutofilledValue();
          if (mCurrentDate.before(mMinDate)) {
              mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
          } else if (mCurrentDate.after(mMaxDate)) {
              mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
          }
      }
  
      @UnsupportedAppUsage
      private void updateSpinners() {
          // set the spinner ranges respecting the min and max dates
          if (mCurrentDate.equals(mMinDate)) {
              mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
              mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
              mDaySpinner.setWrapSelectorWheel(false);
              mMonthSpinner.setDisplayedValues(null);
              mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
              mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
              mMonthSpinner.setWrapSelectorWheel(false);
          } else if (mCurrentDate.equals(mMaxDate)) {
              mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
              mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
              mDaySpinner.setWrapSelectorWheel(false);
              mMonthSpinner.setDisplayedValues(null);
              mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
              mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
              mMonthSpinner.setWrapSelectorWheel(false);
          } else {
              mDaySpinner.setMinValue(1);
              mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
              mDaySpinner.setWrapSelectorWheel(true);
              mMonthSpinner.setDisplayedValues(null);
              mMonthSpinner.setMinValue(0);
              mMonthSpinner.setMaxValue(11);
              mMonthSpinner.setWrapSelectorWheel(true);
          }
  
          // make sure the month names are a zero based array
          // with the months in the month spinner
          String[] displayedValues = Arrays.copyOfRange(mShortMonths,
                  mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
          mMonthSpinner.setDisplayedValues(displayedValues);
  
          // year spinner range does not change based on the current date
          mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
          mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
          mYearSpinner.setWrapSelectorWheel(false);
  
          // set the spinner values
          mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
          mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
          mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
  
          if (usingNumericMonths()) {
              mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
          }
      }
  
      /**
       * Updates the calendar view with the current date.
       */
      @UnsupportedAppUsage
      private void updateCalendarView() {
          mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
      }
  
  
      /**
       * Notifies the listener, if such, for a change in the selected date.
       */
      @UnsupportedAppUsage
      private void notifyDateChanged() {
          mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
          if (mOnDateChangedListener != null) {
              mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
                      getDayOfMonth());
          }
          if (mAutoFillChangeListener != null) {
              mAutoFillChangeListener.onDateChanged(mDelegator, getYear(), getMonth(),
                      getDayOfMonth());
          }
      }
  
      /**
       * Sets the IME options for a spinner based on its ordering.
       *
       * @param spinner The spinner.
       * @param spinnerCount The total spinner count.
       * @param spinnerIndex The index of the given spinner.
       */
      private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
          final int imeOptions;
          if (spinnerIndex < spinnerCount - 1) {
              imeOptions = EditorInfo.IME_ACTION_NEXT;
          } else {
              imeOptions = EditorInfo.IME_ACTION_DONE;
          }
          TextView input = (TextView) spinner.findViewById(com.android.internal.R.id.numberpicker_input);
          input.setImeOptions(imeOptions);
      }
  
      private void setContentDescriptions() {
          // Day
          trySetContentDescription(mDaySpinner, com.android.internal.R.id.increment,
                  com.android.internal.R.string.date_picker_increment_day_button);
          trySetContentDescription(mDaySpinner, com.android.internal.R.id.decrement,
                  com.android.internal.R.string.date_picker_decrement_day_button);
          // Month
          trySetContentDescription(mMonthSpinner, com.android.internal.R.id.increment,
                  com.android.internal.R.string.date_picker_increment_month_button);
          trySetContentDescription(mMonthSpinner, com.android.internal.R.id.decrement,
                  com.android.internal.R.string.date_picker_decrement_month_button);
          // Year
          trySetContentDescription(mYearSpinner, com.android.internal.R.id.increment,
                  com.android.internal.R.string.date_picker_increment_year_button);
          trySetContentDescription(mYearSpinner, com.android.internal.R.id.decrement,
                  com.android.internal.R.string.date_picker_decrement_year_button);
      }
  
      private void trySetContentDescription(View root, int viewId, int contDescResId) {
          View target = root.findViewById(viewId);
          if (target != null) {
              target.setContentDescription(mContext.getString(contDescResId));
          }
      }
  
      @UnsupportedAppUsage
      private void updateInputState() {
          // Make sure that if the user changes the value and the IME is active
          // for one of the inputs if this widget, the IME is closed. If the user
          // changed the value via the IME and there is a next input the IME will
          // be shown, otherwise the user chose another means of changing the
          // value and having the IME up makes no sense.
          InputMethodManager inputMethodManager = mContext.getSystemService(InputMethodManager.class);
          if (inputMethodManager != null) {
              if (inputMethodManager.isActive(mYearSpinnerInput)) {
                  mYearSpinnerInput.clearFocus();
                  inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
              } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
                  mMonthSpinnerInput.clearFocus();
                  inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
              } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
                  mDaySpinnerInput.clearFocus();
                  inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
              }
          }
      }
  }
  