Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(728)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java

Issue 23623019: Support datalist for date/time input types on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
index ac610461f19a6b2f3602b707e2831bf2edb4c5af..1c52fc238b4fd9719790153cb2916a78a8e07eac 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
@@ -13,42 +13,32 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.text.format.DateFormat;
import android.text.format.Time;
+import android.view.View;
+import android.widget.AdapterView;
import android.widget.DatePicker;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
import android.widget.TimePicker;
import org.chromium.content.R;
import org.chromium.content.browser.input.DateTimePickerDialog.OnDateTimeSetListener;
import org.chromium.content.browser.input.MultiFieldTimePickerDialog.OnMultiFieldTimeSetListener;
+import java.util.Arrays;
import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
public class InputDialogContainer {
interface InputActionDelegate {
void cancelDateTimeDialog();
- void replaceDateTime(int dialogType,
- int year, int month, int day, int hour, int minute, int second, int milli, int week);
+ void replaceDateTime(double value);
}
- // Default values used in Time representations of selected date/time before formatting.
- // They are never displayed to the user.
- private static final int YEAR_DEFAULT = 1970;
- private static final int MONTH_DEFAULT = 0;
- private static final int MONTHDAY_DEFAULT = 1;
- private static final int HOUR_DEFAULT = 0;
- private static final int MINUTE_DEFAULT = 0;
- private static final int WEEK_DEFAULT = 0;
-
- // Date formats as accepted by Time.format.
- private static final String HTML_DATE_FORMAT = "%Y-%m-%d";
- private static final String HTML_TIME_FORMAT = "%H:%M";
- // For datetime we always send selected time as UTC, as we have no timezone selector.
- // This is consistent with other browsers.
- private static final String HTML_DATE_TIME_FORMAT = "%Y-%m-%dT%H:%MZ";
- private static final String HTML_DATE_TIME_LOCAL_FORMAT = "%Y-%m-%dT%H:%M";
- private static final String HTML_MONTH_FORMAT = "%Y-%m";
- private static final String HTML_WEEK_FORMAT = "%Y-%w";
-
private static int sTextInputTypeDate;
private static int sTextInputTypeDateTime;
private static int sTextInputTypeDateTimeLocal;
@@ -87,73 +77,176 @@ public class InputDialogContainer {
mInputActionDelegate = inputActionDelegate;
}
- private Time normalizeTime(int year, int month, int monthDay,
- int hour, int minute, int second) {
- Time result = new Time();
- if (year == 0 && month == 0 && monthDay == 0 && hour == 0 &&
- minute == 0 && second == 0) {
- Calendar cal = Calendar.getInstance();
- result.set(cal.get(Calendar.SECOND), cal.get(Calendar.MINUTE),
- cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.DATE),
- cal.get(Calendar.MONTH), cal.get(Calendar.YEAR));
+ void showPickerDialog(final int dialogType, double dialogValue,
+ double min, double max, double step) {
+ Calendar cal;
+ // |dialogValue|, |min|, |max| mean different things depending on the |dialogType|.
+ // For input type=month is the number of months since 1970.
+ // For input type=time it is milliseconds since midnight.
+ // For other types they are just milliseconds since 1970.
+ // If |dialogValue| is NaN it means an empty value. We will show the current time.
+ if (Double.isNaN(dialogValue)) {
+ cal = Calendar.getInstance();
+ cal.set(Calendar.MILLISECOND, 0);
+ } else {
+ if (dialogType == sTextInputTypeMonth) {
+ cal = MonthPicker.createDateFromValue(dialogValue);
+ } else if (dialogType == sTextInputTypeWeek) {
+ cal = WeekPicker.createDateFromValue(dialogValue);
+ } else {
+ GregorianCalendar gregorianCalendar =
+ new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+ // According to the HTML spec we only use the Gregorian calendar
+ // so we ignore the Julian/Gregorian transition.
+ gregorianCalendar.setGregorianChange(new Date(Long.MIN_VALUE));
+ gregorianCalendar.setTimeInMillis((long) dialogValue);
+ cal = gregorianCalendar;
+ }
+ }
+ if (dialogType == sTextInputTypeDate) {
+ showPickerDialog(dialogType,
+ cal.get(Calendar.YEAR),
+ cal.get(Calendar.MONTH),
+ cal.get(Calendar.DAY_OF_MONTH),
+ 0, 0, 0, 0, 0, min, max, step);
+ } else if (dialogType == sTextInputTypeTime) {
+ showPickerDialog(dialogType, 0, 0, 0,
+ cal.get(Calendar.HOUR_OF_DAY),
+ cal.get(Calendar.MINUTE),
+ 0, 0, 0, min, max, step);
+ } else if (dialogType == sTextInputTypeDateTime ||
+ dialogType == sTextInputTypeDateTimeLocal) {
+ showPickerDialog(dialogType,
+ cal.get(Calendar.YEAR),
+ cal.get(Calendar.MONTH),
+ cal.get(Calendar.DAY_OF_MONTH),
+ cal.get(Calendar.HOUR_OF_DAY),
+ cal.get(Calendar.MINUTE),
+ cal.get(Calendar.SECOND),
+ cal.get(Calendar.MILLISECOND),
+ 0, min, max, step);
+ } else if (dialogType == sTextInputTypeMonth) {
+ showPickerDialog(dialogType, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 0,
+ 0, 0, 0, 0, 0, min, max, step);
+ } else if (dialogType == sTextInputTypeWeek) {
+ int year = WeekPicker.getISOWeekYearForDate(cal);
+ int week = WeekPicker.getWeekForDate(cal);
+ showPickerDialog(dialogType, year, 0, 0, 0, 0, 0, 0, week, min, max, step);
+ }
+ }
+
+ void showSuggestionDialog(final int dialogType,
+ final double dialogValue,
+ final double min, final double max, final double step,
+ DateTimeSuggestion[] suggestions) {
+ ListView suggestionListView = new ListView(mContext);
+ final DateTimeSuggestionListAdapter adapter =
+ new DateTimeSuggestionListAdapter(mContext, Arrays.asList(suggestions));
+ suggestionListView.setAdapter(adapter);
+ suggestionListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (position == adapter.getCount() - 1) {
+ dismissDialog();
+ showPickerDialog(dialogType, dialogValue, min, max, step);
+ } else {
+ double suggestionValue = adapter.getItem(position).value();
+ mInputActionDelegate.replaceDateTime(suggestionValue);
+ dismissDialog();
+ mDialogAlreadyDismissed = true;
+ }
+ }
+ });
+
+ int dialogTitleId = R.string.date_picker_dialog_title;
+ if (dialogType == sTextInputTypeTime) {
+ dialogTitleId = R.string.time_picker_dialog_title;
+ } else if (dialogType == sTextInputTypeDateTime ||
+ dialogType == sTextInputTypeDateTimeLocal) {
+ dialogTitleId = R.string.date_time_picker_dialog_title;
+ } else if (dialogType == sTextInputTypeMonth) {
+ dialogTitleId = R.string.month_picker_dialog_title;
+ } else if (dialogType == sTextInputTypeWeek) {
+ dialogTitleId = R.string.week_picker_dialog_title;
+ }
+
+ mDialog = new AlertDialog.Builder(mContext)
+ .setTitle(dialogTitleId)
+ .setView(suggestionListView)
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mDialog == dialog && !mDialogAlreadyDismissed) {
+ mDialogAlreadyDismissed = true;
+ mInputActionDelegate.cancelDateTimeDialog();
+ }
+ }
+ })
+ .setNegativeButton(mContext.getText(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dismissDialog();
+ }
+ })
+ .create();
+
+ mDialogAlreadyDismissed = false;
+ mDialog.show();
+ }
+
+ void showDialog(final int type, final double value,
+ double min, double max, double step,
+ DateTimeSuggestion[] suggestions) {
+ // When the web page asks to show a dialog while there is one already open,
+ // dismiss the old one.
+ dismissDialog();
+ if (suggestions == null) {
+ showPickerDialog(type, value, min, max, step);
} else {
- result.set(second, minute, hour, monthDay, month, year);
+ showSuggestionDialog(type, value, min, max, step, suggestions);
}
- return result;
}
- void showDialog(final int dialogType, int year, int month, int monthDay,
- int hour, int minute, int second, int milli, int week,
- double min, double max, double step) {
+ void showPickerDialog(final int dialogType,
+ int year, int month, int monthDay,
+ int hourOfDay, int minute, int second, int millis, int week,
+ double min, double max, double step) {
if (isDialogShowing()) mDialog.dismiss();
- // Java Date dialogs like longs but Blink prefers doubles..
- // Both parameters mean different things depending on the type
- // For input type=month min and max come as number on months since 1970
- // For other types (including type=time) they are just milliseconds since 1970
- // In any case the cast here is safe given the above restrictions.
- long minTime = (long) min;
- long maxTime = (long) max;
int stepTime = (int) step;
- if (milli > 1000) {
- second += milli / 1000;
- milli %= 1000;
- }
- Time time = normalizeTime(year, month, monthDay, hour, minute, second);
if (dialogType == sTextInputTypeDate) {
DatePickerDialog dialog = new DatePickerDialog(mContext,
- new DateListener(dialogType), time.year, time.month, time.monthDay);
+ new DateListener(dialogType),
+ year, month, monthDay);
DateDialogNormalizer.normalize(dialog.getDatePicker(), dialog,
- time.year, time.month, time.monthDay, 0, 0, minTime, maxTime);
+ year, month, monthDay,
+ 0, 0,
+ (long) min, (long) max);
bulach 2013/12/04 10:37:54 nit: as above, perhaps best to change this method
keishi 2013/12/04 12:21:24 DateDialogNormalizer will only take min/max as num
dialog.setTitle(mContext.getText(R.string.date_picker_dialog_title));
mDialog = dialog;
} else if (dialogType == sTextInputTypeTime) {
mDialog = new MultiFieldTimePickerDialog(
mContext, 0 /* theme */ ,
- time.hour, time.minute, time.second, milli,
- (int) minTime, (int) maxTime, stepTime,
+ hourOfDay, minute, second, millis,
+ (int) min, (int) max, stepTime,
DateFormat.is24HourFormat(mContext),
new FullTimeListener(dialogType));
} else if (dialogType == sTextInputTypeDateTime ||
dialogType == sTextInputTypeDateTimeLocal) {
mDialog = new DateTimePickerDialog(mContext,
new DateTimeListener(dialogType),
- time.year, time.month, time.monthDay,
- time.hour, time.minute, DateFormat.is24HourFormat(mContext),
- minTime, maxTime);
+ year, month, monthDay,
+ hourOfDay, minute,
+ DateFormat.is24HourFormat(mContext), min, max);
} else if (dialogType == sTextInputTypeMonth) {
mDialog = new MonthPickerDialog(mContext, new MonthOrWeekListener(dialogType),
- time.year, time.month, minTime, maxTime);
+ year, month, min, max);
} else if (dialogType == sTextInputTypeWeek) {
- if (week == 0) {
- Calendar cal = Calendar.getInstance();
- year = WeekPicker.getISOWeekYearForDate(cal);
- week = WeekPicker.getWeekForDate(cal);
- }
mDialog = new WeekPickerDialog(mContext, new MonthOrWeekListener(dialogType),
- year, week, minTime, maxTime);
+ year, week, min, max);
}
mDialog.setButton(DialogInterface.BUTTON_POSITIVE,
@@ -170,7 +263,7 @@ public class InputDialogContainer {
@Override
public void onClick(DialogInterface dialog, int which) {
mDialogAlreadyDismissed = true;
- mInputActionDelegate.replaceDateTime(dialogType, 0, 0, 0, 0, 0, 0, 0, 0);
+ mInputActionDelegate.replaceDateTime(Double.NaN);
}
});
@@ -206,29 +299,7 @@ public class InputDialogContainer {
@Override
public void onDateSet(DatePicker view, int year, int month, int monthDay) {
- if (!mDialogAlreadyDismissed) {
- setFieldDateTimeValue(mDialogType,
- year, month, monthDay,
- HOUR_DEFAULT, MINUTE_DEFAULT, WEEK_DEFAULT,
- HTML_DATE_FORMAT);
- }
- }
- }
-
- private class TimeListener implements OnTimeSetListener {
- private final int mDialogType;
-
- TimeListener(int dialogType) {
- mDialogType = dialogType;
- }
-
- @Override
- public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
- if (!mDialogAlreadyDismissed) {
- setFieldDateTimeValue(mDialogType,
- YEAR_DEFAULT, MONTH_DEFAULT, MONTHDAY_DEFAULT,
- hourOfDay, minute, WEEK_DEFAULT, HTML_TIME_FORMAT);
- }
+ setFieldDateTimeValue(mDialogType, year, month, monthDay, 0, 0, 0, 0, 0);
}
}
@@ -240,11 +311,7 @@ public class InputDialogContainer {
@Override
public void onTimeSet(int hourOfDay, int minute, int second, int milli) {
- if (!mDialogAlreadyDismissed) {
- setFieldDateTimeValue(mDialogType,
- YEAR_DEFAULT, MONTH_DEFAULT, MONTHDAY_DEFAULT,
- hourOfDay, minute, second, milli, WEEK_DEFAULT, HTML_TIME_FORMAT);
- }
+ setFieldDateTimeValue(mDialogType, 0, 0, 0, hourOfDay, minute, second, milli, 0);
}
}
@@ -261,11 +328,7 @@ public class InputDialogContainer {
public void onDateTimeSet(DatePicker dateView, TimePicker timeView,
int year, int month, int monthDay,
int hourOfDay, int minute) {
- if (!mDialogAlreadyDismissed) {
- setFieldDateTimeValue(mDialogType, year, month, monthDay,
- hourOfDay, minute, WEEK_DEFAULT,
- mLocal ? HTML_DATE_TIME_LOCAL_FORMAT : HTML_DATE_TIME_FORMAT);
- }
+ setFieldDateTimeValue(mDialogType, year, month, monthDay, hourOfDay, minute, 0, 0, 0);
}
}
@@ -278,38 +341,46 @@ public class InputDialogContainer {
@Override
public void onValueSet(int year, int positionInYear) {
- if (!mDialogAlreadyDismissed) {
- if (mDialogType == sTextInputTypeMonth) {
- setFieldDateTimeValue(mDialogType, year, positionInYear, MONTHDAY_DEFAULT,
- HOUR_DEFAULT, MINUTE_DEFAULT, WEEK_DEFAULT,
- HTML_MONTH_FORMAT);
- } else {
- setFieldDateTimeValue(mDialogType, year, MONTH_DEFAULT, MONTHDAY_DEFAULT,
- HOUR_DEFAULT, MINUTE_DEFAULT, positionInYear, HTML_WEEK_FORMAT);
- }
+ if (mDialogType == sTextInputTypeMonth) {
+ setFieldDateTimeValue(mDialogType, year, positionInYear, 0, 0, 0, 0, 0, 0);
+ } else {
+ setFieldDateTimeValue(mDialogType, year, 0, 0, 0, 0, 0, 0, positionInYear);
}
}
}
- private void setFieldDateTimeValue(int dialogType,
- int year, int month, int monthDay, int hourOfDay,
- int minute, int week, String dateFormat) {
+ protected void setFieldDateTimeValue(int dialogType,
+ int year, int month, int monthDay,
+ int hourOfDay, int minute, int second, int millis,
+ int week) {
// Prevents more than one callback being sent to the native
// side when the dialog triggers multiple events.
+ if (mDialogAlreadyDismissed)
+ return;
mDialogAlreadyDismissed = true;
- mInputActionDelegate.replaceDateTime(dialogType,
- year, month, monthDay, hourOfDay, minute, 0 /* second */, 0 /* milli */, week);
- }
-
- private void setFieldDateTimeValue(int dialogType,
- int year, int month, int monthDay, int hourOfDay,
- int minute, int second, int milli, int week, String dateFormat) {
- // Prevents more than one callback being sent to the native
- // side when the dialog triggers multiple events.
- mDialogAlreadyDismissed = true;
-
- mInputActionDelegate.replaceDateTime(
- dialogType, year, month, monthDay, hourOfDay, minute, second, milli, week);
+ double value = 0;
+ if (dialogType == sTextInputTypeMonth) {
+ mInputActionDelegate.replaceDateTime((year - 1970) * 12 + month);
+ } else if (dialogType == sTextInputTypeWeek) {
+ mInputActionDelegate.replaceDateTime(
+ WeekPicker.createDateFromWeek(year, week).getTimeInMillis());
+ } else if (dialogType == sTextInputTypeTime) {
+ mInputActionDelegate.replaceDateTime(TimeUnit.HOURS.toMillis(hourOfDay) +
+ TimeUnit.MINUTES.toMillis(minute) +
+ TimeUnit.SECONDS.toMillis(second) +
+ millis);
+ } else {
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ cal.clear();
bulach 2013/12/04 10:37:54 nit: unindent
keishi 2013/12/04 12:21:24 Done.
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.MONTH, month);
+ cal.set(Calendar.DAY_OF_MONTH, monthDay);
+ cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ cal.set(Calendar.MINUTE, minute);
+ cal.set(Calendar.SECOND, second);
+ cal.set(Calendar.MILLISECOND, millis);
+ mInputActionDelegate.replaceDateTime((double) cal.getTimeInMillis());
+ }
}
}

Powered by Google App Engine
This is Rietveld 408576698