1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.contacts.datepicker;
18 
19 // This is a fork of the standard Android DatePicker that additionally allows toggling the year
20 // on/off.
21 
22 import android.app.AlertDialog;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.DialogInterface.OnClickListener;
26 import android.os.Bundle;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 
30 import com.android.contacts.R;
31 import com.android.contacts.datepicker.DatePicker.OnDateChangedListener;
32 import com.android.contacts.util.DateUtils;
33 
34 import java.text.DateFormat;
35 import java.util.Calendar;
36 
37 /**
38  * A simple dialog containing an {@link DatePicker}.
39  *
40  * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker
41  * tutorial</a>.</p>
42  */
43 public class DatePickerDialog extends AlertDialog implements OnClickListener,
44         OnDateChangedListener {
45 
46     /** Magic year that represents "no year" */
47     public static int NO_YEAR = DatePicker.NO_YEAR;
48 
49     private static final String YEAR = "year";
50     private static final String MONTH = "month";
51     private static final String DAY = "day";
52     private static final String YEAR_OPTIONAL = "year_optional";
53 
54     private final DatePicker mDatePicker;
55     private final OnDateSetListener mCallBack;
56     private final DateFormat mTitleDateFormat;
57     private final DateFormat mTitleNoYearDateFormat;
58 
59     private int mInitialYear;
60     private int mInitialMonth;
61     private int mInitialDay;
62 
63     /**
64      * The callback used to indicate the user is done filling in the date.
65      */
66     public interface OnDateSetListener {
67         /**
68          * @param view The view associated with this listener.
69          * @param year The year that was set or {@link DatePickerDialog#NO_YEAR} if the user has
70          *  not specified a year
71          * @param monthOfYear The month that was set (0-11) for compatibility
72          *  with {@link java.util.Calendar}.
73          * @param dayOfMonth The day of the month that was set.
74          */
onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)75         void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth);
76     }
77 
78     /**
79      * @param context The context the dialog is to run in.
80      * @param callBack How the parent is notified that the date is set.
81      * @param year The initial year of the dialog
82      * @param monthOfYear The initial month of the dialog.
83      * @param dayOfMonth The initial day of the dialog.
84      */
DatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth)85     public DatePickerDialog(Context context,
86             OnDateSetListener callBack,
87             int year,
88             int monthOfYear,
89             int dayOfMonth) {
90         this(context, callBack, year, monthOfYear, dayOfMonth, false);
91     }
92 
93     /**
94      * @param context The context the dialog is to run in.
95      * @param callBack How the parent is notified that the date is set.
96      * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no year
97      *  has been specified
98      * @param monthOfYear The initial month of the dialog.
99      * @param dayOfMonth The initial day of the dialog.
100      * @param yearOptional Whether the year can be toggled by the user
101      */
DatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth, boolean yearOptional)102     public DatePickerDialog(Context context,
103             OnDateSetListener callBack,
104             int year,
105             int monthOfYear,
106             int dayOfMonth,
107             boolean yearOptional) {
108         // Don't pass a theme id. Instead use the default alert dialog theme.
109         this(context, /* themeId = */ -1, callBack, year, monthOfYear, dayOfMonth,
110                 yearOptional);
111     }
112 
113     /**
114      * @param context The context the dialog is to run in.
115      * @param theme the theme to apply to this dialog
116      * @param callBack How the parent is notified that the date is set.
117      * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no year
118      *  has been specified
119      * @param monthOfYear The initial month of the dialog.
120      * @param dayOfMonth The initial day of the dialog.
121      */
DatePickerDialog(Context context, int theme, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth)122     public DatePickerDialog(Context context,
123             int theme,
124             OnDateSetListener callBack,
125             int year,
126             int monthOfYear,
127             int dayOfMonth) {
128         this(context, theme, callBack, year, monthOfYear, dayOfMonth, false);
129     }
130 
131     /**
132      * @param context The context the dialog is to run in.
133      * @param theme the theme to apply to this dialog
134      * @param callBack How the parent is notified that the date is set.
135      * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no
136      *  year has been specified.
137      * @param monthOfYear The initial month of the dialog.
138      * @param dayOfMonth The initial day of the dialog.
139      * @param yearOptional Whether the year can be toggled by the user
140      */
DatePickerDialog(Context context, int theme, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth, boolean yearOptional)141     public DatePickerDialog(Context context,
142             int theme,
143             OnDateSetListener callBack,
144             int year,
145             int monthOfYear,
146             int dayOfMonth,
147             boolean yearOptional) {
148         super(context, theme);
149 
150         mCallBack = callBack;
151         mInitialYear = year;
152         mInitialMonth = monthOfYear;
153         mInitialDay = dayOfMonth;
154 
155         mTitleDateFormat = DateFormat.getDateInstance(DateFormat.FULL);
156         mTitleNoYearDateFormat = DateUtils.getLocalizedDateFormatWithoutYear(getContext());
157         updateTitle(mInitialYear, mInitialMonth, mInitialDay);
158 
159         setButton(BUTTON_POSITIVE, context.getText(R.string.date_time_set),
160                 this);
161         setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel),
162                 (OnClickListener) null);
163 
164         LayoutInflater inflater =
165                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
166         View view = inflater.inflate(R.layout.date_picker_dialog, null);
167         setView(view);
168         mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
169         mDatePicker.init(mInitialYear, mInitialMonth, mInitialDay, yearOptional, this);
170     }
171 
172     @Override
onClick(DialogInterface dialog, int which)173     public void onClick(DialogInterface dialog, int which) {
174         if (mCallBack != null) {
175             mDatePicker.clearFocus();
176             mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(),
177                     mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
178         }
179     }
180 
181     @Override
onDateChanged(DatePicker view, int year, int month, int day)182     public void onDateChanged(DatePicker view, int year, int month, int day) {
183         updateTitle(year, month, day);
184     }
185 
updateDate(int year, int monthOfYear, int dayOfMonth)186     public void updateDate(int year, int monthOfYear, int dayOfMonth) {
187         mInitialYear = year;
188         mInitialMonth = monthOfYear;
189         mInitialDay = dayOfMonth;
190         mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
191     }
192 
updateTitle(int year, int month, int day)193     private void updateTitle(int year, int month, int day) {
194         final Calendar calendar = Calendar.getInstance();
195         calendar.set(Calendar.YEAR, year);
196         calendar.set(Calendar.MONTH, month);
197         calendar.set(Calendar.DAY_OF_MONTH, day);
198         final DateFormat dateFormat =
199                 year == NO_YEAR ? mTitleNoYearDateFormat : mTitleDateFormat;
200         setTitle(dateFormat.format(calendar.getTime()));
201     }
202 
203     @Override
onSaveInstanceState()204     public Bundle onSaveInstanceState() {
205         Bundle state = super.onSaveInstanceState();
206         state.putInt(YEAR, mDatePicker.getYear());
207         state.putInt(MONTH, mDatePicker.getMonth());
208         state.putInt(DAY, mDatePicker.getDayOfMonth());
209         state.putBoolean(YEAR_OPTIONAL, mDatePicker.isYearOptional());
210         return state;
211     }
212 
213     @Override
onRestoreInstanceState(Bundle savedInstanceState)214     public void onRestoreInstanceState(Bundle savedInstanceState) {
215         super.onRestoreInstanceState(savedInstanceState);
216         int year = savedInstanceState.getInt(YEAR);
217         int month = savedInstanceState.getInt(MONTH);
218         int day = savedInstanceState.getInt(DAY);
219         boolean yearOptional = savedInstanceState.getBoolean(YEAR_OPTIONAL);
220         mDatePicker.init(year, month, day, yearOptional, this);
221         updateTitle(year, month, day);
222     }
223 }
224