DatePickerCalendarDelegate.java revision 68640b68099765461d5427fddbb925beaa9d2a6a
1bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/*
2bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Copyright (C) 2014 The Android Open Source Project
3bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *
4bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License");
5bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * you may not use this file except in compliance with the License.
6bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * You may obtain a copy of the License at
7bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *
8bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *      http://www.apache.org/licenses/LICENSE-2.0
9bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio *
10bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software
11bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS,
12bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * See the License for the specific language governing permissions and
14bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * limitations under the License.
15bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */
16bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
17bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Megliopackage android.widget;
18bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
196b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viveretteimport com.android.internal.R;
206b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette
210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.annotation.Nullable;
22bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.Context;
23bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.ColorStateList;
24bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.Configuration;
25bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.Resources;
26bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.TypedArray;
27c3e5a82691ac9094189a000430eab939e9020b2bAlan Viveretteimport android.icu.text.DisplayContext;
28c3e5a82691ac9094189a000430eab939e9020b2bAlan Viveretteimport android.icu.text.SimpleDateFormat;
2968763be41cffbcb4883a0a6293fc1aa9e17a3957Alan Viveretteimport android.icu.util.Calendar;
30bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.os.Parcelable;
31bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.text.format.DateFormat;
32bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.text.format.DateUtils;
33bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.util.AttributeSet;
340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.StateSet;
35bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.HapticFeedbackConstants;
36bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.LayoutInflater;
37bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.View;
380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.View.OnClickListener;
390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.view.ViewGroup;
40bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.view.accessibility.AccessibilityEvent;
410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.DayPickerView.OnDaySelectedListener;
420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.widget.YearPickerView.OnYearSelectedListener;
43bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
44bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Locale;
45bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
46bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/**
47bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * A delegate for picking up a date (day / month / year).
48bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */
490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteclass DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
500a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette    private static final int USE_LOCALE = 0;
51bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
52bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private static final int UNINITIALIZED = -1;
530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int VIEW_MONTH_DAY = 0;
540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private static final int VIEW_YEAR = 1;
55bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
56bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private static final int DEFAULT_START_YEAR = 1900;
57bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private static final int DEFAULT_END_YEAR = 2100;
58bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
59bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private static final int ANIMATION_DURATION = 300;
60bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
6160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private static final int[] ATTRS_TEXT_COLOR = new int[] {
6260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette            com.android.internal.R.attr.textColor};
6360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette    private static final int[] ATTRS_DISABLED_ALPHA = new int[] {
640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            com.android.internal.R.attr.disabledAlpha};
65bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private SimpleDateFormat mYearFormat;
670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private SimpleDateFormat mMonthDayFormat;
687119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette
690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    // Top-level container.
700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private ViewGroup mContainer;
717119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette
720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    // Header views.
730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private TextView mHeaderYear;
740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private TextView mHeaderMonthDay;
757119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette
760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    // Picker views.
770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private ViewAnimator mAnimator;
78bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private DayPickerView mDayPickerView;
79bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private YearPickerView mYearPickerView;
80bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
81bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    // Accessibility strings.
82bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private String mSelectDay;
83bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private String mSelectYear;
84bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
85bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private int mCurrentView = UNINITIALIZED;
86bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
87452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette    private final Calendar mCurrentDate;
88452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette    private final Calendar mTempDate;
89452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette    private final Calendar mMinDate;
90452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette    private final Calendar mMaxDate;
91bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
920a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette    private int mFirstDayOfWeek = USE_LOCALE;
930a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette
943053b2fdcf7486f2e2f572f9b05ce65dacdd2b4cChet Haase    public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs,
95bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            int defStyleAttr, int defStyleRes) {
96bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        super(delegator, context);
97bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final Locale locale = mCurrentLocale;
99452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette        mCurrentDate = Calendar.getInstance(locale);
100452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette        mTempDate = Calendar.getInstance(locale);
101452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette        mMinDate = Calendar.getInstance(locale);
102452fe349841476e4c7d17ab0652bdd4d45ce4595Alan Viverette        mMaxDate = Calendar.getInstance(locale);
103bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
10449e6c4adbfad8cac28a0c7c68918b443a64a07d8You Kim        mMinDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1);
10549e6c4adbfad8cac28a0c7c68918b443a64a07d8You Kim        mMaxDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31);
106bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
10760727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette        final Resources res = mDelegator.getResources();
108bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final TypedArray a = mContext.obtainStyledAttributes(attrs,
109bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                R.styleable.DatePicker, defStyleAttr, defStyleRes);
110bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
111bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                Context.LAYOUT_INFLATER_SERVICE);
112bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final int layoutResourceId = a.getResourceId(
1130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                R.styleable.DatePicker_internalLayout, R.layout.date_picker_material);
1140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up and attach container.
116f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator, false);
117f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mDelegator.addView(mContainer);
118bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
1190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up header views.
1200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
1210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
1220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mHeaderYear.setOnClickListener(mOnHeaderClickListener);
1230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
1240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
125ba9bf41a77261471a4dc9d7964aec41726b4e4e6Alan Viverette
1260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // For the sake of backwards compatibility, attempt to extract the text
1270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // color from the header month text appearance. If it's set, we'll let
1280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // that override the "real" header text color.
1290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        ColorStateList headerTextColor = null;
130bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
1310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        @SuppressWarnings("deprecation")
1320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int monthHeaderTextAppearance = a.getResourceId(
1334e5168fae43e783a35c5bc731e500196005268fbAlan Viverette                R.styleable.DatePicker_headerMonthTextAppearance, 0);
1340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (monthHeaderTextAppearance != 0) {
1350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final TypedArray textAppearance = mContext.obtainStyledAttributes(null,
1360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    ATTRS_TEXT_COLOR, 0, monthHeaderTextAppearance);
1370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final ColorStateList legacyHeaderTextColor = textAppearance.getColorStateList(0);
1380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            headerTextColor = applyLegacyColorFixes(legacyHeaderTextColor);
1390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            textAppearance.recycle();
140bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
14160727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette
1420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (headerTextColor == null) {
1430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            headerTextColor = a.getColorStateList(R.styleable.DatePicker_headerTextColor);
14460727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette        }
14560727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette
1460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (headerTextColor != null) {
1470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            mHeaderYear.setTextColor(headerTextColor);
1480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            mHeaderMonthDay.setTextColor(headerTextColor);
14960727e07c6ef72e2f494266939c02494a3df28f8Alan Viverette        }
150bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
1510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up header background, if available.
1520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (a.hasValueOrEmpty(R.styleable.DatePicker_headerBackground)) {
1530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            header.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
1540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
1550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
15660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette        a.recycle();
15760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette
1580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up picker container.
1590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
1600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up day picker view.
1620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
163e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
1644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
1654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
1664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
167e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
16850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette
1690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up year picker view.
1700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
1712a90fa6d94b7d31e997493d2d0601e5129ec7c3eAlan Viverette        mYearPickerView.setRange(mMinDate, mMaxDate);
172e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount        mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
1730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
1744e5168fae43e783a35c5bc731e500196005268fbAlan Viverette
1750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Set up content descriptions.
176bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mSelectDay = res.getString(R.string.select_day);
177bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mSelectYear = res.getString(R.string.select_year);
178bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
1790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Initialize for current locale. This also initializes the date, so no
1800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // need to call onDateChanged.
1810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        onLocaleChanged(mCurrentLocale);
1820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setCurrentView(VIEW_MONTH_DAY);
1840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
1850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
1860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
1870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * The legacy text color might have been poorly defined. Ensures that it
1880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * has an appropriate activated state, using the selected state if one
1890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * exists or modifying the default text color otherwise.
1900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *
1910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @param color a legacy text color, or {@code null}
1920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * @return a color state list with an appropriate activated state, or
1930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     *         {@code null} if a valid activated state could not be generated
1940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
1950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Nullable
1960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private ColorStateList applyLegacyColorFixes(@Nullable ColorStateList color) {
1970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (color == null || color.hasState(R.attr.state_activated)) {
1980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            return color;
1990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int activatedColor;
2020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int defaultColor;
2030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (color.hasState(R.attr.state_selected)) {
2040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            activatedColor = color.getColorForState(StateSet.get(
2050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_SELECTED), 0);
2060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            defaultColor = color.getColorForState(StateSet.get(
2070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    StateSet.VIEW_STATE_ENABLED), 0);
2080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        } else {
2090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            activatedColor = color.getDefaultColor();
2100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // Generate a non-activated color using the disabled alpha.
2120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final TypedArray ta = mContext.obtainStyledAttributes(ATTRS_DISABLED_ALPHA);
2130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final float disabledAlpha = ta.getFloat(0, 0.30f);
2140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            defaultColor = multiplyAlphaComponent(activatedColor, disabledAlpha);
2150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2167119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette
2170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (activatedColor == 0 || defaultColor == 0) {
2180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // We somehow failed to obtain the colors.
2190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            return null;
2200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2217119d0d66bd8649508c5bbb973a34b3b858bf8cfAlan Viverette
2220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int[][] stateSet = new int[][] {{ R.attr.state_activated }, {}};
2230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int[] colors = new int[] { activatedColor, defaultColor };
2240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return new ColorStateList(stateSet, colors);
2250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
226bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
2270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private int multiplyAlphaComponent(int color, float alphaMod) {
2280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int srcRgb = color & 0xFFFFFF;
2290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int srcAlpha = (color >> 24) & 0xFF;
2300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int dstAlpha = (int) (srcAlpha * alphaMod + 0.5f);
2310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return srcRgb | (dstAlpha << 24);
232bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
233bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
234bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    /**
2350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Listener called when the user selects a day in the day picker view.
2360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
2370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final OnDaySelectedListener mOnDaySelectedListener = new OnDaySelectedListener() {
2380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        @Override
2390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        public void onDaySelected(DayPickerView view, Calendar day) {
2400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            mCurrentDate.setTimeInMillis(day.getTimeInMillis());
2410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            onDateChanged(true, true);
2420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    };
2440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
2460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Listener called when the user selects a year in the year picker view.
2470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
2480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final OnYearSelectedListener mOnYearSelectedListener = new OnYearSelectedListener() {
2490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        @Override
2500ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        public void onYearChanged(YearPickerView view, int year) {
2510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // If the newly selected month / year does not contain the
2520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // currently selected day number, change the selected day number
2530ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // to the last day of the selected month or year.
2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
2550ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
2570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int month = mCurrentDate.get(Calendar.MONTH);
2580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int daysInMonth = getDaysInMonth(month, year);
2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            if (day > daysInMonth) {
2600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth);
2610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            mCurrentDate.set(Calendar.YEAR, year);
2640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            onDateChanged(true, true);
2650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // Automatically switch to day picker.
2670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            setCurrentView(VIEW_MONTH_DAY);
268e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount
269e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            // Switch focus back to the year text.
270e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount            mHeaderYear.requestFocus();
2710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    };
2730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    /**
2750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     * Listener called when the user clicks on a header item.
2760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette     */
2770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private final OnClickListener mOnHeaderClickListener = new OnClickListener() {
2780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        @Override
2790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        public void onClick(View v) {
2800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            tryVibrate();
2810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            switch (v.getId()) {
2830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                case R.id.date_picker_header_year:
2840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    setCurrentView(VIEW_YEAR);
2850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    break;
2860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                case R.id.date_picker_header_date:
2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    setCurrentView(VIEW_MONTH_DAY);
2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    break;
2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            }
2900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        }
2910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    };
2920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
2930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    @Override
2940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    protected void onLocaleChanged(Locale locale) {
2950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final TextView headerYear = mHeaderYear;
2960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (headerYear == null) {
2970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // Abort, we haven't initialized yet. This method will get called
2980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // again later after everything has been set up.
2990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            return;
300bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
301bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3020ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Update the date formatter.
3030ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String datePattern = DateFormat.getBestDateTimePattern(locale, "EMMMd");
3040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mMonthDayFormat = new SimpleDateFormat(datePattern, locale);
305c3e5a82691ac9094189a000430eab939e9020b2bAlan Viverette        mMonthDayFormat.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE);
3060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mYearFormat = new SimpleDateFormat("y", locale);
307bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // Update the header text.
3090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        onCurrentDateChanged(false);
3100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    }
311bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private void onCurrentDateChanged(boolean announce) {
3130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mHeaderYear == null) {
3140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // Abort, we haven't initialized yet. This method will get called
3150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            // again later after everything has been set up.
3160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            return;
317bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
318bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String year = mYearFormat.format(mCurrentDate.getTime());
3200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mHeaderYear.setText(year);
321bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final String monthDay = mMonthDayFormat.format(mCurrentDate.getTime());
3230ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mHeaderMonthDay.setText(monthDay);
324bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
3250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        // TODO: This should use live regions.
326bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        if (announce) {
3270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final long millis = mCurrentDate.getTimeInMillis();
3280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
3290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            final String fullDateText = DateUtils.formatDateTime(mContext, millis, flags);
330bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            mAnimator.announceForAccessibility(fullDateText);
331bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
332bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
333bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
334bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    private void setCurrentView(final int viewIndex) {
335bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        switch (viewIndex) {
3360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            case VIEW_MONTH_DAY:
3370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
3380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
339bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                if (mCurrentView != viewIndex) {
3400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mHeaderMonthDay.setActivated(true);
3410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mHeaderYear.setActivated(false);
3420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mAnimator.setDisplayedChild(VIEW_MONTH_DAY);
343bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                    mCurrentView = viewIndex;
344bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                }
345bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
346bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                mAnimator.announceForAccessibility(mSelectDay);
347bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                break;
3480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette            case VIEW_YEAR:
349e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                final int year = mCurrentDate.get(Calendar.YEAR);
350e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                mYearPickerView.setYear(year);
351e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                mYearPickerView.post(new Runnable() {
352e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                    @Override
353e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                    public void run() {
354e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                        mYearPickerView.requestFocus();
355e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                        final View selected = mYearPickerView.getSelectedView();
356e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                        if (selected != null) {
357e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                            selected.requestFocus();
358e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                        }
359e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                    }
360e998c3f5f6e7ac21b18cd449088ac2b76b65671fGeorge Mount                });
3610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
362bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                if (mCurrentView != viewIndex) {
3630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mHeaderMonthDay.setActivated(false);
3640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mHeaderYear.setActivated(true);
3650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette                    mAnimator.setDisplayedChild(VIEW_YEAR);
366bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                    mCurrentView = viewIndex;
367bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                }
368bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
369bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                mAnimator.announceForAccessibility(mSelectYear);
370bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                break;
371bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
372bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
373bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
374bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
375bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void init(int year, int monthOfYear, int dayOfMonth,
376bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            DatePicker.OnDateChangedListener callBack) {
377bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mCurrentDate.set(Calendar.YEAR, year);
378bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mCurrentDate.set(Calendar.MONTH, monthOfYear);
379bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
380e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette
3810cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette        onDateChanged(false, false);
382a9a75f506efe7e63078bed661f49992e501846f0Alan Viverette
38368640b68099765461d5427fddbb925beaa9d2a6aClara Bayarri        mOnDateChangedListener = callBack;
384bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
385bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
386bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
387bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void updateDate(int year, int month, int dayOfMonth) {
388bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mCurrentDate.set(Calendar.YEAR, year);
389bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mCurrentDate.set(Calendar.MONTH, month);
390bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
391e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette
3920cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette        onDateChanged(false, true);
393e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette    }
394e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette
3950cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette    private void onDateChanged(boolean fromUser, boolean callbackToClient) {
3960ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        final int year = mCurrentDate.get(Calendar.YEAR);
3970ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette
39868640b68099765461d5427fddbb925beaa9d2a6aClara Bayarri        if (callbackToClient && mOnDateChangedListener != null) {
399e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette            final int monthOfYear = mCurrentDate.get(Calendar.MONTH);
400e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette            final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH);
40168640b68099765461d5427fddbb925beaa9d2a6aClara Bayarri            mOnDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth);
402e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette        }
403e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette
4040ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
4050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        mYearPickerView.setYear(year);
406e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette
4070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        onCurrentDateChanged(fromUser);
408e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette
409e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette        if (fromUser) {
410e6ec07fc5d7ce7732f63b6da73d3cc9e207df69fAlan Viverette            tryVibrate();
4119468c6a28e696f4ddca2c5b9ba312ffb590c3161Alan Viverette        }
412bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
413bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
414bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
415bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public int getYear() {
416bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return mCurrentDate.get(Calendar.YEAR);
417bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
418bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
419bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
420bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public int getMonth() {
421bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return mCurrentDate.get(Calendar.MONTH);
422bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
423bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
424bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
425bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public int getDayOfMonth() {
426bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return mCurrentDate.get(Calendar.DAY_OF_MONTH);
427bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
428bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
429bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
430bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void setMinDate(long minDate) {
431bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mTempDate.setTimeInMillis(minDate);
432bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
4333fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette                && mTempDate.get(Calendar.DAY_OF_YEAR) == mMinDate.get(Calendar.DAY_OF_YEAR)) {
4343fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette            // Same day, no-op.
435bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            return;
436bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
437bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        if (mCurrentDate.before(mTempDate)) {
438bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            mCurrentDate.setTimeInMillis(minDate);
4390cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette            onDateChanged(false, true);
440bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
441bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mMinDate.setTimeInMillis(minDate);
4424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mDayPickerView.setMinDate(minDate);
44350eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        mYearPickerView.setRange(mMinDate, mMaxDate);
444bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
445bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
446bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
447bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public Calendar getMinDate() {
448bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return mMinDate;
449bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
450bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
451bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
452bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void setMaxDate(long maxDate) {
453bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mTempDate.setTimeInMillis(maxDate);
454bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
4553fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette                && mTempDate.get(Calendar.DAY_OF_YEAR) == mMaxDate.get(Calendar.DAY_OF_YEAR)) {
4563fb5c7b8fac6fd5583da10793d0bfa40bc851ed5Alan Viverette            // Same day, no-op.
457bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            return;
458bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
459bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        if (mCurrentDate.after(mTempDate)) {
460bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            mCurrentDate.setTimeInMillis(maxDate);
4610cecbc9c7208f918ddf9d117057649f6e132069fAlan Viverette            onDateChanged(false, true);
462bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
463bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mMaxDate.setTimeInMillis(maxDate);
4644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette        mDayPickerView.setMaxDate(maxDate);
46550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette        mYearPickerView.setRange(mMinDate, mMaxDate);
466bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
467bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
468bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
469bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public Calendar getMaxDate() {
470bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return mMaxDate;
471bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
472bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
473bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
4740a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette    public void setFirstDayOfWeek(int firstDayOfWeek) {
4750a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette        mFirstDayOfWeek = firstDayOfWeek;
476e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette
477e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette        mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
4780a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette    }
4790a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette
4800a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette    @Override
481bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public int getFirstDayOfWeek() {
4820a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette        if (mFirstDayOfWeek != USE_LOCALE) {
4830a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette            return mFirstDayOfWeek;
4840a04bb0d4bf18318fe5473bf5615c2016bc26373Alan Viverette        }
485bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return mCurrentDate.getFirstDayOfWeek();
486bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
487bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
488bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
489bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void setEnabled(boolean enabled) {
490f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mContainer.setEnabled(enabled);
491f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mDayPickerView.setEnabled(enabled);
492f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mYearPickerView.setEnabled(enabled);
493f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mHeaderYear.setEnabled(enabled);
494f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        mHeaderMonthDay.setEnabled(enabled);
495bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
496bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
497bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
498bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public boolean isEnabled() {
4990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        return mContainer.isEnabled();
500bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
501bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
502bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
503bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public CalendarView getCalendarView() {
504f7aa9251d091d0e52e879a8a92bd38228e58efd9Alan Viverette        throw new UnsupportedOperationException("Not supported by calendar-mode DatePicker");
505bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
506bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
507bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
508bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void setCalendarViewShown(boolean shown) {
509bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        // No-op for compatibility with the old DatePicker.
510bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
511bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
512bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
513bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public boolean getCalendarViewShown() {
514bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return false;
515bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
516bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
517bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
518bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void setSpinnersShown(boolean shown) {
519bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        // No-op for compatibility with the old DatePicker.
520bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
521bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
522bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
523bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public boolean getSpinnersShown() {
524bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return false;
525bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
526bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
527bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
528bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void onConfigurationChanged(Configuration newConfig) {
5290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        setCurrentLocale(newConfig.locale);
530bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
531bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
532bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
533bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public Parcelable onSaveInstanceState(Parcelable superState) {
534bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final int year = mCurrentDate.get(Calendar.YEAR);
535bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final int month = mCurrentDate.get(Calendar.MONTH);
536bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
537bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
538bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        int listPosition = -1;
539bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        int listPositionOffset = -1;
540bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
5410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        if (mCurrentView == VIEW_MONTH_DAY) {
542bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            listPosition = mDayPickerView.getMostVisiblePosition();
5430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette        } else if (mCurrentView == VIEW_YEAR) {
544bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            listPosition = mYearPickerView.getFirstVisiblePosition();
545bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            listPositionOffset = mYearPickerView.getFirstPositionOffset();
546bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
547bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
548bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return new SavedState(superState, year, month, day, mMinDate.getTimeInMillis(),
549bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                mMaxDate.getTimeInMillis(), mCurrentView, listPosition, listPositionOffset);
550bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
551bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
552bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
553bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void onRestoreInstanceState(Parcelable state) {
5546b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette        if (state instanceof SavedState) {
5556b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            final SavedState ss = (SavedState) state;
5566b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette
5576b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            // TODO: Move instance state into DayPickerView, YearPickerView.
5586b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
5596b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            mMinDate.setTimeInMillis(ss.getMinDate());
5606b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            mMaxDate.setTimeInMillis(ss.getMaxDate());
5616b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette
5626b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            onCurrentDateChanged(false);
5636b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette
5646b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            final int currentView = ss.getCurrentView();
5656b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            setCurrentView(currentView);
5666b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette
5676b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            final int listPosition = ss.getListPosition();
5686b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette            if (listPosition != -1) {
5696b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette                if (currentView == VIEW_MONTH_DAY) {
5706b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette                    mDayPickerView.setPosition(listPosition);
5716b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette                } else if (currentView == VIEW_YEAR) {
5726b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette                    final int listPositionOffset = ss.getListPositionOffset();
5736b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette                    mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
5746b3f85f87ed95cce748aeb57c70df0d2ed72707fAlan Viverette                }
575bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            }
576bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
577bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
578bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
579bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
580bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
581bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        onPopulateAccessibilityEvent(event);
582bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        return true;
583bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
584bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
585bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    @Override
586bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
587bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        event.getText().add(mCurrentDate.getTime().toString());
588bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
589bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
590a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn    public CharSequence getAccessibilityClassName() {
591a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn        return DatePicker.class.getName();
592bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
593bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
594bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    public static int getDaysInMonth(int month, int year) {
595bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        switch (month) {
596bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.JANUARY:
597bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.MARCH:
598bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.MAY:
599bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.JULY:
600bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.AUGUST:
601bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.OCTOBER:
602bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.DECEMBER:
603bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                return 31;
604bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.APRIL:
605bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.JUNE:
606bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.SEPTEMBER:
607bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.NOVEMBER:
608bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                return 30;
609bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            case Calendar.FEBRUARY:
610bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                return (year % 4 == 0) ? 29 : 28;
611bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio            default:
612bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio                throw new IllegalArgumentException("Invalid Month");
613bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        }
614bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
615bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio
6160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette    private void tryVibrate() {
617bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio        mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
618bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio    }
619bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio}
620