Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / content / public / android / java / src / org / chromium / content / browser / input / MultiFieldTimePickerDialog.java
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.content.browser.input;
6
7 import android.app.AlertDialog;
8 import android.content.Context;
9 import android.content.DialogInterface;
10 import android.content.DialogInterface.OnClickListener;
11 import android.view.LayoutInflater;
12 import android.view.View;
13 import android.widget.NumberPicker;
14
15 import org.chromium.content.R;
16
17 import java.util.ArrayList;
18
19 /**
20  * A time picker dialog with upto 5 number pickers left to right:
21  *  hour, minute, second, milli, AM/PM.
22  *
23  * If is24hourFormat is true then AM/PM picker is not displayed and
24  * hour range is 0..23. Otherwise hour range is 1..12.
25  * The milli picker is not displayed if step >= SECOND_IN_MILLIS
26  * The second picker is not displayed if step >= MINUTE_IN_MILLIS.
27  */
28 public class MultiFieldTimePickerDialog
29         extends AlertDialog implements OnClickListener {
30
31     private final NumberPicker mHourSpinner;
32     private final NumberPicker mMinuteSpinner;
33     private final NumberPicker mSecSpinner;
34     private final NumberPicker mMilliSpinner;
35     private final NumberPicker mAmPmSpinner;
36     private final OnMultiFieldTimeSetListener mListener;
37     private final int mStep;
38     private final int mBaseMilli;
39     private final boolean mIs24hourFormat;
40
41     public interface OnMultiFieldTimeSetListener {
42         void onTimeSet(int hourOfDay, int minute, int second, int milli);
43     }
44
45     private static final int SECOND_IN_MILLIS = 1000;
46     private static final int MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS;
47     private static final int HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
48
49     public MultiFieldTimePickerDialog(
50             Context context,
51             int theme,
52             int hour, int minute, int second, int milli,
53             int min, int max, int step, boolean is24hourFormat,
54             OnMultiFieldTimeSetListener listener) {
55         super(context, theme);
56         mListener = listener;
57         mStep = step;
58         mIs24hourFormat = is24hourFormat;
59
60         if (min >= max) {
61             min = 0;
62             max = 24 * HOUR_IN_MILLIS - 1;
63         }
64         if (step < 0 || step >= 24 * HOUR_IN_MILLIS) {
65             step = MINUTE_IN_MILLIS;
66         }
67
68         LayoutInflater inflater =
69                 (LayoutInflater) context.getSystemService(
70                         Context.LAYOUT_INFLATER_SERVICE);
71         View view = inflater.inflate(R.layout.multi_field_time_picker_dialog, null);
72         setView(view);
73
74         mHourSpinner = (NumberPicker) view.findViewById(R.id.hour);
75         mMinuteSpinner = (NumberPicker) view.findViewById(R.id.minute);
76         mSecSpinner = (NumberPicker) view.findViewById(R.id.second);
77         mMilliSpinner = (NumberPicker) view.findViewById(R.id.milli);
78         mAmPmSpinner = (NumberPicker) view.findViewById(R.id.ampm);
79
80         int minHour = min / HOUR_IN_MILLIS;
81         int maxHour = max / HOUR_IN_MILLIS;
82         min -= minHour * HOUR_IN_MILLIS;
83         max -= maxHour * HOUR_IN_MILLIS;
84
85         if (minHour == maxHour) {
86             mHourSpinner.setEnabled(false);
87             hour = minHour;
88         }
89
90         if (is24hourFormat) {
91             mAmPmSpinner.setVisibility(View.GONE);
92         } else {
93             int minAmPm = minHour / 12;
94             int maxAmPm = maxHour / 12;
95             int amPm = hour / 12;
96             mAmPmSpinner.setMinValue(minAmPm);
97             mAmPmSpinner.setMaxValue(maxAmPm);
98             mAmPmSpinner.setDisplayedValues(new String[] {
99                     context.getString(R.string.time_picker_dialog_am),
100                     context.getString(R.string.time_picker_dialog_pm)
101             });
102
103             hour %= 12;
104             if (hour == 0) {
105                 hour = 12;
106             }
107             if (minAmPm == maxAmPm) {
108                 mAmPmSpinner.setEnabled(false);
109                 amPm = minAmPm;
110
111                 minHour %= 12;
112                 maxHour %= 12;
113                 if (minHour == 0 && maxHour == 0) {
114                     minHour = 12;
115                     maxHour = 12;
116                 } else if (minHour == 0) {
117                     minHour = maxHour;
118                     maxHour = 12;
119                 } else if (maxHour == 0) {
120                     maxHour = 12;
121                 }
122             } else {
123                 minHour = 1;
124                 maxHour = 12;
125             }
126             mAmPmSpinner.setValue(amPm);
127         }
128
129         if (minHour == maxHour) {
130             mHourSpinner.setEnabled(false);
131         }
132         mHourSpinner.setMinValue(minHour);
133         mHourSpinner.setMaxValue(maxHour);
134         mHourSpinner.setValue(hour);
135
136         NumberFormatter twoDigitPaddingFormatter = new NumberFormatter("%02d");
137
138         int minMinute = min / MINUTE_IN_MILLIS;
139         int maxMinute = max / MINUTE_IN_MILLIS;
140         min -= minMinute * MINUTE_IN_MILLIS;
141         max -= maxMinute * MINUTE_IN_MILLIS;
142
143         if (minHour == maxHour) {
144             mMinuteSpinner.setMinValue(minMinute);
145             mMinuteSpinner.setMaxValue(maxMinute);
146             if (minMinute == maxMinute) {
147                 // Set this otherwise the box is empty until you stroke it.
148                 mMinuteSpinner.setDisplayedValues(
149                     new String[] { twoDigitPaddingFormatter.format(minMinute) });
150                 mMinuteSpinner.setEnabled(false);
151                 minute = minMinute;
152             }
153         } else {
154             mMinuteSpinner.setMinValue(0);
155             mMinuteSpinner.setMaxValue(59);
156         }
157
158         if (step >= HOUR_IN_MILLIS) {
159             mMinuteSpinner.setEnabled(false);
160         }
161
162         mMinuteSpinner.setValue(minute);
163         mMinuteSpinner.setFormatter(twoDigitPaddingFormatter);
164
165         if (step >= MINUTE_IN_MILLIS) {
166             // Remove the ':' in front of the second spinner as well.
167             view.findViewById(R.id.second_colon).setVisibility(View.GONE);
168             mSecSpinner.setVisibility(View.GONE);
169         }
170
171         int minSecond = min / SECOND_IN_MILLIS;
172         int maxSecond = max / SECOND_IN_MILLIS;
173         min -= minSecond * SECOND_IN_MILLIS;
174         max -= maxSecond * SECOND_IN_MILLIS;
175
176         if (minHour == maxHour && minMinute == maxMinute) {
177             mSecSpinner.setMinValue(minSecond);
178             mSecSpinner.setMaxValue(maxSecond);
179             if (minSecond == maxSecond) {
180                 // Set this otherwise the box is empty until you stroke it.
181                 mSecSpinner.setDisplayedValues(
182                     new String[] { twoDigitPaddingFormatter.format(minSecond) });
183                 mSecSpinner.setEnabled(false);
184                 second = minSecond;
185             }
186         } else {
187             mSecSpinner.setMinValue(0);
188             mSecSpinner.setMaxValue(59);
189         }
190
191         mSecSpinner.setValue(second);
192         mSecSpinner.setFormatter(twoDigitPaddingFormatter);
193
194         if (step >= SECOND_IN_MILLIS) {
195             // Remove the '.' in front of the milli spinner as well.
196             view.findViewById(R.id.second_dot).setVisibility(View.GONE);
197             mMilliSpinner.setVisibility(View.GONE);
198         }
199
200         // Round to the nearest step.
201         milli = ((milli + step / 2) / step) * step;
202         if (step == 1 || step == 10 || step == 100) {
203             if (minHour == maxHour && minMinute == maxMinute &&
204                 minSecond == maxSecond) {
205                 mMilliSpinner.setMinValue(min / step);
206                 mMilliSpinner.setMaxValue(max / step);
207
208                 if (min == max) {
209                     mMilliSpinner.setEnabled(false);
210                     milli = min;
211                 }
212             } else {
213                 mMilliSpinner.setMinValue(0);
214                 mMilliSpinner.setMaxValue(999 / step);
215             }
216
217             if (step == 1) {
218                 mMilliSpinner.setFormatter(new NumberFormatter("%03d"));
219             } else if (step == 10) {
220                 mMilliSpinner.setFormatter(new NumberFormatter("%02d"));
221             } else if (step == 100) {
222                 mMilliSpinner.setFormatter(new NumberFormatter("%d"));
223             }
224             mMilliSpinner.setValue(milli / step);
225             mBaseMilli = 0;
226         } else if (step < SECOND_IN_MILLIS) {
227             // Non-decimal step value.
228             ArrayList<String> strValue = new ArrayList<String>();
229             for (int i = min; i < max; i += step) {
230                 strValue.add(String.format("%03d", i));
231             }
232             mMilliSpinner.setMinValue(0);
233             mMilliSpinner.setMaxValue(strValue.size() - 1);
234             mMilliSpinner.setValue((milli - min) / step);
235             mMilliSpinner.setDisplayedValues(
236                 strValue.toArray(new String[strValue.size()]));
237             mBaseMilli = min;
238         } else {
239             mBaseMilli = 0;
240         }
241     }
242
243     @Override
244     public void onClick(DialogInterface dialog, int which) {
245         notifyDateSet();
246     }
247
248     private void notifyDateSet() {
249         int hour = mHourSpinner.getValue();
250         int minute = mMinuteSpinner.getValue();
251         int sec = mSecSpinner.getValue();
252         int milli = mMilliSpinner.getValue() * mStep + mBaseMilli;
253         if (!mIs24hourFormat) {
254             int ampm = mAmPmSpinner.getValue();
255             if (hour == 12) {
256                 hour = 0;
257             }
258             hour += ampm * 12;
259         }
260         mListener.onTimeSet(hour, minute, sec, milli);
261     }
262
263     private static class NumberFormatter implements NumberPicker.Formatter {
264         private final String mFormat;
265
266         NumberFormatter(String format) {
267             mFormat = format;
268         }
269
270         @Override
271         public String format(int value) {
272             return String.format(mFormat, value);
273         }
274     }
275 }