summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorleandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-03 12:31:16 +0000
committerleandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-03 12:31:16 +0000
commiteb7be252bd1c0861a15d4776dc4ae0ffc49c10c5 (patch)
tree5dfe1fd773d3cd2b6cdcd6bee5dce66a095aa157 /content
parent3bcafa841e3c3405fee6bfb11012b240309c1752 (diff)
downloadchromium_src-eb7be252bd1c0861a15d4776dc4ae0ffc49c10c5.zip
chromium_src-eb7be252bd1c0861a15d4776dc4ae0ffc49c10c5.tar.gz
chromium_src-eb7be252bd1c0861a15d4776dc4ae0ffc49c10c5.tar.bz2
[Android] Add UI pickers.
CL 10626017 introduced a new interface for app resources, enabling to upstream these. BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/10664016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145291 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/public/android/java/src/org/chromium/content/app/AppResource.java36
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java208
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/MonthPicker.java481
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java151
4 files changed, 876 insertions, 0 deletions
diff --git a/content/public/android/java/src/org/chromium/content/app/AppResource.java b/content/public/android/java/src/org/chromium/content/app/AppResource.java
index 4178702..3bd7f60 100644
--- a/content/public/android/java/src/org/chromium/content/app/AppResource.java
+++ b/content/public/android/java/src/org/chromium/content/app/AppResource.java
@@ -21,6 +21,42 @@ public class AppResource {
/** Drawable resource for the link preview popup overlay. */
public static int DRAWABLE_LINK_PREVIEW_POPUP_OVERLAY;
+ /** Id of the date picker view. */
+ public static int ID_DATE_PICKER;
+
+ /** Id of the month picker view. */
+ public static int ID_MONTH_PICKER;
+
+ /** Id of the time picker view. */
+ public static int ID_TIME_PICKER;
+
+ /** Id of the year picker view. */
+ public static int ID_YEAR_PICKER;
+
+ /** Id of the view containing the month and year pickers. */
+ public static int ID_MONTH_YEAR_PICKERS_CONTAINER;
+
+ /** Layout of the date/time picker dialog. */
+ public static int LAYOUT_DATE_TIME_PICKER_DIALOG;
+
+ /** Layout of the month picker. */
+ public static int LAYOUT_MONTH_PICKER;
+
+ /** Layout of the month picker dialog. */
+ public static int LAYOUT_MONTH_PICKER_DIALOG;
+
+ /** String for the Clear button in the date picker dialog. */
+ public static int STRING_DATE_PICKER_DIALOG_CLEAR;
+
+ /** String for the Set button in the date picker dialog. */
+ public static int STRING_DATE_PICKER_DIALOG_SET;
+
+ /** String for the title of the date/time picker dialog. */
+ public static int STRING_DATE_TIME_PICKER_DIALOG_TITLE;
+
+ /** String for the title of the month picker dialog. */
+ public static int STRING_MONTH_PICKER_DIALOG_TITLE;
+
/**
* Iterates through all the resources ids and verifies they have values other than zero.
* @return true if all the resources have been registered.
diff --git a/content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java
new file mode 100644
index 0000000..409b88c
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/DateTimePickerDialog.java
@@ -0,0 +1,208 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.DatePicker;
+import android.widget.TimePicker;
+import android.widget.DatePicker.OnDateChangedListener;
+import android.widget.TimePicker.OnTimeChangedListener;
+
+import org.chromium.content.app.AppResource;
+
+class DateTimePickerDialog extends AlertDialog implements OnClickListener,
+ OnDateChangedListener, OnTimeChangedListener {
+
+ private static final String YEAR = "year";
+ private static final String MONTH = "month";
+ private static final String DAY = "day";
+ private static final String HOUR = "hour";
+ private static final String MINUTE = "minute";
+ private static final String IS_24_HOUR = "is24hour";
+
+ private final DatePicker mDatePicker;
+ private final TimePicker mTimePicker;
+ private final OnDateTimeSetListener mCallBack;
+
+ /**
+ * The callback used to indicate the user is done filling in the date.
+ */
+ public interface OnDateTimeSetListener {
+
+ /**
+ * @param dateView The DatePicker view associated with this listener.
+ * @param timeView The TimePicker view associated with this listener.
+ * @param year The year that was set.
+ * @param monthOfYear The month that was set (0-11) for compatibility
+ * with {@link java.util.Calendar}.
+ * @param dayOfMonth The day of the month that was set.
+ * @param hourOfDay The hour that was set.
+ * @param minute The minute that was set.
+ */
+ void onDateTimeSet(DatePicker dateView, TimePicker timeView, int year, int monthOfYear,
+ int dayOfMonth, int hourOfDay, int minute);
+ }
+
+ /**
+ * @param context The context the dialog is to run in.
+ * @param callBack How the parent is notified that the date is set.
+ * @param year The initial year of the dialog.
+ * @param monthOfYear The initial month of the dialog.
+ * @param dayOfMonth The initial day of the dialog.
+ */
+ public DateTimePickerDialog(Context context,
+ OnDateTimeSetListener callBack,
+ int year,
+ int monthOfYear,
+ int dayOfMonth,
+ int hourOfDay, int minute, boolean is24HourView) {
+ this(context, 0, callBack, year, monthOfYear, dayOfMonth,
+ hourOfDay, minute, is24HourView);
+ }
+
+ /**
+ * @param context The context the dialog is to run in.
+ * @param theme the theme to apply to this dialog
+ * @param callBack How the parent is notified that the date is set.
+ * @param year The initial year of the dialog.
+ * @param monthOfYear The initial month of the dialog.
+ * @param dayOfMonth The initial day of the dialog.
+ */
+ public DateTimePickerDialog(Context context,
+ int theme,
+ OnDateTimeSetListener callBack,
+ int year,
+ int monthOfYear,
+ int dayOfMonth,
+ int hourOfDay, int minute, boolean is24HourView) {
+ super(context, theme);
+
+ mCallBack = callBack;
+
+ assert AppResource.STRING_DATE_PICKER_DIALOG_SET != 0;
+ assert AppResource.STRING_DATE_TIME_PICKER_DIALOG_TITLE != 0;
+ assert AppResource.LAYOUT_DATE_TIME_PICKER_DIALOG != 0;
+ assert AppResource.ID_DATE_PICKER != 0;
+ assert AppResource.ID_TIME_PICKER != 0;
+
+ setButton(BUTTON_POSITIVE, context.getText(
+ AppResource.STRING_DATE_PICKER_DIALOG_SET), this);
+ setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel),
+ (OnClickListener) null);
+ setIcon(0);
+ setTitle(context.getText(AppResource.STRING_DATE_TIME_PICKER_DIALOG_TITLE));
+
+ LayoutInflater inflater =
+ (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View view = inflater.inflate(AppResource.LAYOUT_DATE_TIME_PICKER_DIALOG, null);
+ setView(view);
+ mDatePicker = (DatePicker) view.findViewById(AppResource.ID_DATE_PICKER);
+ mDatePicker.init(year, monthOfYear, dayOfMonth, this);
+
+ mTimePicker = (TimePicker) view.findViewById(AppResource.ID_TIME_PICKER);
+ mTimePicker.setIs24HourView(is24HourView);
+ mTimePicker.setCurrentHour(hourOfDay);
+ mTimePicker.setCurrentMinute(minute);
+ mTimePicker.setOnTimeChangedListener(this);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ tryNotifyDateTimeSet();
+ }
+
+ private void tryNotifyDateTimeSet() {
+ if (mCallBack != null) {
+ mDatePicker.clearFocus();
+ mCallBack.onDateTimeSet(mDatePicker, mTimePicker, mDatePicker.getYear(),
+ mDatePicker.getMonth(), mDatePicker.getDayOfMonth(),
+ mTimePicker.getCurrentHour(), mTimePicker.getCurrentMinute());
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ if (Build.VERSION.SDK_INT >= 16) {
+ tryNotifyDateTimeSet();
+ }
+ super.onStop();
+ }
+
+ @Override
+ public void onDateChanged(DatePicker view, int year,
+ int month, int day) {
+ mDatePicker.init(year, month, day, null);
+ }
+
+ @Override
+ public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
+ /* do nothing */
+ }
+
+ /**
+ * Gets the {@link DatePicker} contained in this dialog.
+ *
+ * @return The DatePicker view.
+ */
+ public DatePicker getDatePicker() {
+ return mDatePicker;
+ }
+
+ /**
+ * Gets the {@link TimePicker} contained in this dialog.
+ *
+ * @return The TimePicker view.
+ */
+ public TimePicker getTimePicker() {
+ return mTimePicker;
+ }
+
+ /**
+ * Sets the current date.
+ *
+ * @param year The date year.
+ * @param monthOfYear The date month.
+ * @param dayOfMonth The date day of month.
+ */
+ public void updateDateTime(int year, int monthOfYear, int dayOfMonth,
+ int hourOfDay, int minutOfHour) {
+ mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
+ mTimePicker.setCurrentHour(hourOfDay);
+ mTimePicker.setCurrentMinute(minutOfHour);
+ }
+
+ @Override
+ public Bundle onSaveInstanceState() {
+ Bundle state = super.onSaveInstanceState();
+ state.putInt(YEAR, mDatePicker.getYear());
+ state.putInt(MONTH, mDatePicker.getMonth());
+ state.putInt(DAY, mDatePicker.getDayOfMonth());
+ state.putInt(HOUR, mTimePicker.getCurrentHour());
+ state.putInt(MINUTE, mTimePicker.getCurrentMinute());
+ state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView());
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ int year = savedInstanceState.getInt(YEAR);
+ int month = savedInstanceState.getInt(MONTH);
+ int day = savedInstanceState.getInt(DAY);
+ mDatePicker.init(year, month, day, this);
+ int hour = savedInstanceState.getInt(HOUR);
+ int minute = savedInstanceState.getInt(MINUTE);
+ mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
+ mTimePicker.setCurrentHour(hour);
+ mTimePicker.setCurrentMinute(minute);
+ }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/MonthPicker.java b/content/public/android/java/src/org/chromium/content/browser/MonthPicker.java
new file mode 100644
index 0000000..f70a771
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/MonthPicker.java
@@ -0,0 +1,481 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.DatePicker;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.NumberPicker;
+import android.widget.NumberPicker.OnValueChangeListener;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.chromium.content.app.AppResource;
+
+// This class is heavily based on android.widget.DatePicker.
+public class MonthPicker extends FrameLayout {
+
+ private static final int DEFAULT_START_YEAR = 1900;
+
+ private static final int DEFAULT_END_YEAR = 2100;
+
+ private static final boolean DEFAULT_ENABLED_STATE = true;
+
+ private final LinearLayout mSpinners;
+
+ private final NumberPicker mMonthSpinner;
+
+ private final NumberPicker mYearSpinner;
+
+ private Locale mCurrentLocale;
+
+ private OnMonthChangedListener mMonthChangedListener;
+
+ private String[] mShortMonths;
+
+ private int mNumberOfMonths;
+
+ private Calendar mTempDate;
+
+ private Calendar mMinDate;
+
+ private Calendar mMaxDate;
+
+ private Calendar mCurrentDate;
+
+ private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
+ /**
+ * The callback used to indicate the user changes\d the date.
+ */
+ public interface OnMonthChangedListener {
+
+ /**
+ * Called upon a date change.
+ *
+ * @param view The view associated with this listener.
+ * @param year The year that was set.
+ * @param monthOfYear The month that was set (0-11) for compatibility
+ * with {@link java.util.Calendar}.
+ */
+ void onMonthChanged(MonthPicker view, int year, int monthOfYear);
+ }
+
+ public MonthPicker(Context context) {
+ this(context, null);
+ }
+
+ public MonthPicker(Context context, AttributeSet attrs) {
+ this(context, attrs, android.R.attr.datePickerStyle);
+ }
+
+ public MonthPicker(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ // initialization based on locale
+ setCurrentLocale(Locale.getDefault());
+
+ int startYear = DEFAULT_START_YEAR;
+ int endYear = DEFAULT_END_YEAR;
+
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ assert AppResource.LAYOUT_MONTH_PICKER != 0;
+ inflater.inflate(AppResource.LAYOUT_MONTH_PICKER, this, true);
+
+ OnValueChangeListener onChangeListener = new OnValueChangeListener() {
+ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+ mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
+ // take care of wrapping of days and months to update greater fields
+ if (picker == mMonthSpinner) {
+ if (oldVal == 11 && newVal == 0) {
+ mTempDate.add(Calendar.MONTH, 1);
+ } else if (oldVal == 0 && newVal == 11) {
+ mTempDate.add(Calendar.MONTH, -1);
+ } else {
+ mTempDate.add(Calendar.MONTH, newVal - oldVal);
+ }
+ } else if (picker == mYearSpinner) {
+ mTempDate.set(Calendar.YEAR, newVal);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ // now set the date to the adjusted one
+ setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH));
+ updateSpinners();
+ notifyDateChanged();
+ }
+ };
+
+ assert AppResource.ID_MONTH_YEAR_PICKERS_CONTAINER != 0;
+ mSpinners = (LinearLayout) findViewById(AppResource.ID_MONTH_YEAR_PICKERS_CONTAINER);
+
+ // month
+ assert AppResource.ID_MONTH_PICKER != 0;
+ mMonthSpinner = (NumberPicker) findViewById(AppResource.ID_MONTH_PICKER);
+ mMonthSpinner.setMinValue(0);
+ mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
+ mMonthSpinner.setDisplayedValues(mShortMonths);
+ mMonthSpinner.setOnLongPressUpdateInterval(200);
+ mMonthSpinner.setOnValueChangedListener(onChangeListener);
+
+ // year
+ assert AppResource.ID_YEAR_PICKER != 0;
+ mYearSpinner = (NumberPicker) findViewById(AppResource.ID_YEAR_PICKER);
+ mYearSpinner.setOnLongPressUpdateInterval(100);
+ mYearSpinner.setOnValueChangedListener(onChangeListener);
+
+ mTempDate.clear();
+ mTempDate.set(startYear, 0, 1);
+
+ setMinDate(mTempDate.getTimeInMillis());
+
+ mTempDate.clear();
+ mTempDate.set(endYear, 11, 31);
+ setMaxDate(mTempDate.getTimeInMillis());
+
+ // initialize to current date
+ mCurrentDate.setTimeInMillis(System.currentTimeMillis());
+ init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), null);
+ }
+
+ /**
+ * Gets the minimal date supported by this {@link DatePicker} in
+ * milliseconds since January 1, 1970 00:00:00 in
+ * {@link TimeZone#getDefault()} time zone.
+ * <p>
+ * Note: The default minimal date is 01/01/1900.
+ * <p>
+ *
+ * @return The minimal supported date.
+ */
+ public long getMinDate() {
+ return mMinDate.getTimeInMillis();
+ }
+
+ /**
+ * Sets the minimal date supported by this {@link NumberPicker} in
+ * milliseconds since January 1, 1970 00:00:00 in
+ * {@link TimeZone#getDefault()} time zone.
+ *
+ * @param minDate The minimal supported date.
+ */
+ public void setMinDate(long minDate) {
+ mTempDate.setTimeInMillis(minDate);
+ if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ mMinDate.setTimeInMillis(minDate);
+ if (mCurrentDate.before(mMinDate)) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ }
+ updateSpinners();
+ }
+
+ /**
+ * Gets the maximal date supported by this {@link DatePicker} in
+ * milliseconds since January 1, 1970 00:00:00 in
+ * {@link TimeZone#getDefault()} time zone.
+ * <p>
+ * Note: The default maximal date is 12/31/2100.
+ * <p>
+ *
+ * @return The maximal supported date.
+ */
+ public long getMaxDate() {
+ return mMaxDate.getTimeInMillis();
+ }
+
+ /**
+ * Sets the maximal date supported by this {@link DatePicker} in
+ * milliseconds since January 1, 1970 00:00:00 in
+ * {@link TimeZone#getDefault()} time zone.
+ *
+ * @param maxDate The maximal supported date.
+ */
+ public void setMaxDate(long maxDate) {
+ mTempDate.setTimeInMillis(maxDate);
+ if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ mMaxDate.setTimeInMillis(maxDate);
+ if (mCurrentDate.after(mMaxDate)) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ }
+ updateSpinners();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (mIsEnabled == enabled) {
+ return;
+ }
+ super.setEnabled(enabled);
+ mMonthSpinner.setEnabled(enabled);
+ mYearSpinner.setEnabled(enabled);
+ mIsEnabled = enabled;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ onPopulateAccessibilityEvent(event);
+ return true;
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
+ final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
+ String selectedDateUtterance = DateUtils.formatDateTime(getContext(),
+ mCurrentDate.getTimeInMillis(), flags);
+ event.getText().add(selectedDateUtterance);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ setCurrentLocale(newConfig.locale);
+ }
+
+ /**
+ * Sets the current locale.
+ *
+ * @param locale The current locale.
+ */
+ private void setCurrentLocale(Locale locale) {
+ if (locale.equals(mCurrentLocale)) {
+ return;
+ }
+
+ mCurrentLocale = locale;
+
+ mTempDate = getCalendarForLocale(mTempDate, locale);
+ mMinDate = getCalendarForLocale(mMinDate, locale);
+ mMaxDate = getCalendarForLocale(mMaxDate, locale);
+ mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+ mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+ mShortMonths = new String[mNumberOfMonths];
+ for (int i = 0; i < mNumberOfMonths; i++) {
+ mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
+ DateUtils.LENGTH_MEDIUM);
+ }
+ }
+
+ /**
+ * Gets a calendar for locale bootstrapped with the value of a given calendar.
+ *
+ * @param oldCalendar The old calendar.
+ * @param locale The locale.
+ */
+ private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+ if (oldCalendar == null) {
+ return Calendar.getInstance(locale);
+ } else {
+ final long currentTimeMillis = oldCalendar.getTimeInMillis();
+ Calendar newCalendar = Calendar.getInstance(locale);
+ newCalendar.setTimeInMillis(currentTimeMillis);
+ return newCalendar;
+ }
+ }
+
+ /**
+ * Updates the current date.
+ *
+ * @param year The year.
+ * @param month The month which is <strong>starting from zero</strong>.
+ */
+ public void updateMonth(int year, int month) {
+ if (!isNewDate(year, month)) {
+ return;
+ }
+ setDate(year, month);
+ updateSpinners();
+ notifyDateChanged();
+ }
+
+ // Override so we are in complete control of save / restore for this widget.
+ @Override
+ protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ dispatchThawSelfOnly(container);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ return new SavedState(superState, getYear(), getMonth());
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ setDate(ss.mYear, ss.mMonth);
+ updateSpinners();
+ }
+
+ /**
+ * Initialize the state. If the provided values designate an inconsistent
+ * date the values are normalized before updating the spinners.
+ *
+ * @param year The initial year.
+ * @param monthOfYear The initial month <strong>starting from zero</strong>.
+ * @param onMonthChangedListener How user is notified date is changed by
+ * user, can be null.
+ */
+ public void init(int year, int monthOfYear, OnMonthChangedListener onMonthChangedListener) {
+ setDate(year, monthOfYear);
+ updateSpinners();
+ mMonthChangedListener = onMonthChangedListener;
+ }
+
+ private boolean isNewDate(int year, int month) {
+ return (mCurrentDate.get(Calendar.YEAR) != year
+ || mCurrentDate.get(Calendar.MONTH) != month);
+ }
+
+ private void setDate(int year, int month) {
+ mCurrentDate.set(year, month, 1);
+ if (mCurrentDate.before(mMinDate)) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ } else if (mCurrentDate.after(mMaxDate)) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ }
+ }
+
+ private void updateSpinners() {
+ // set the spinner ranges respecting the min and max dates
+ if (mCurrentDate.equals(mMinDate)) {
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
+ mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+ mMonthSpinner.setWrapSelectorWheel(false);
+ } else if (mCurrentDate.equals(mMaxDate)) {
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
+ mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
+ mMonthSpinner.setWrapSelectorWheel(false);
+ } else {
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(0);
+ mMonthSpinner.setMaxValue(11);
+ mMonthSpinner.setWrapSelectorWheel(true);
+ }
+
+ // make sure the month names are a zero based array
+ // with the months in the month spinner
+ String[] displayedValues = Arrays.copyOfRange(mShortMonths,
+ mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
+ mMonthSpinner.setDisplayedValues(displayedValues);
+
+ // year spinner range does not change based on the current date
+ mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
+ mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
+ mYearSpinner.setWrapSelectorWheel(false);
+
+ // set the spinner values
+ mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
+ mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
+ }
+
+ /**
+ * @return The selected year.
+ */
+ public int getYear() {
+ return mCurrentDate.get(Calendar.YEAR);
+ }
+
+ /**
+ * @return The selected month.
+ */
+ public int getMonth() {
+ return mCurrentDate.get(Calendar.MONTH);
+ }
+
+ /**
+ * @return The selected day of month.
+ */
+ public int getDayOfMonth() {
+ return mCurrentDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ /**
+ * Notifies the listener, if such, for a change in the selected date.
+ */
+ private void notifyDateChanged() {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ if (mMonthChangedListener != null) {
+ mMonthChangedListener.onMonthChanged(this, getYear(), getMonth());
+ }
+ }
+
+ /**
+ * Class for managing state storing/restoring.
+ */
+ private static class SavedState extends BaseSavedState {
+
+ private final int mYear;
+
+ private final int mMonth;
+
+ /**
+ * Constructor called from {@link DatePicker#onSaveInstanceState()}
+ */
+ private SavedState(Parcelable superState, int year, int month) {
+ super(superState);
+ mYear = year;
+ mMonth = month;
+ }
+
+ /**
+ * Constructor called from {@link #CREATOR}
+ */
+ private SavedState(Parcel in) {
+ super(in);
+ mYear = in.readInt();
+ mMonth = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mYear);
+ dest.writeInt(mMonth);
+ }
+
+ @SuppressWarnings("all")
+ // suppress unused and hiding
+ public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java b/content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java
new file mode 100644
index 0000000..23fe793
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/MonthPickerDialog.java
@@ -0,0 +1,151 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import org.chromium.content.app.AppResource;
+import org.chromium.content.browser.MonthPicker.OnMonthChangedListener;
+
+public class MonthPickerDialog extends AlertDialog implements OnClickListener,
+ OnMonthChangedListener {
+
+ private static final String YEAR = "year";
+ private static final String MONTH = "month";
+
+ private final MonthPicker mMonthPicker;
+ private final OnMonthSetListener mCallBack;
+
+ /**
+ * The callback used to indicate the user is done filling in the date.
+ */
+ public interface OnMonthSetListener {
+
+ /**
+ * @param view The view associated with this listener.
+ * @param year The year that was set.
+ * @param monthOfYear The month that was set (0-11) for compatibility
+ * with {@link java.util.Calendar}.
+ */
+ void onMonthSet(MonthPicker view, int year, int monthOfYear);
+ }
+
+ /**
+ * @param context The context the dialog is to run in.
+ * @param callBack How the parent is notified that the date is set.
+ * @param year The initial year of the dialog.
+ * @param monthOfYear The initial month of the dialog.
+ */
+ public MonthPickerDialog(Context context,
+ OnMonthSetListener callBack,
+ int year,
+ int monthOfYear) {
+ this(context, 0, callBack, year, monthOfYear);
+ }
+
+ /**
+ * @param context The context the dialog is to run in.
+ * @param theme the theme to apply to this dialog
+ * @param callBack How the parent is notified that the date is set.
+ * @param year The initial year of the dialog.
+ * @param monthOfYear The initial month of the dialog.
+ */
+ public MonthPickerDialog(Context context,
+ int theme,
+ OnMonthSetListener callBack,
+ int year,
+ int monthOfYear) {
+ super(context, theme);
+
+ mCallBack = callBack;
+
+ assert AppResource.STRING_DATE_PICKER_DIALOG_SET != 0;
+ assert AppResource.STRING_MONTH_PICKER_DIALOG_TITLE != 0;
+ assert AppResource.LAYOUT_MONTH_PICKER_DIALOG != 0;
+ assert AppResource.ID_DATE_PICKER != 0;
+
+ setButton(BUTTON_POSITIVE, context.getText(
+ AppResource.STRING_DATE_PICKER_DIALOG_SET), this);
+ setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel),
+ (OnClickListener) null);
+ setIcon(0);
+ setTitle(AppResource.STRING_MONTH_PICKER_DIALOG_TITLE);
+
+ LayoutInflater inflater =
+ (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View view = inflater.inflate(AppResource.LAYOUT_MONTH_PICKER_DIALOG, null);
+ setView(view);
+ mMonthPicker = (MonthPicker) view.findViewById(AppResource.ID_DATE_PICKER);
+ mMonthPicker.init(year, monthOfYear, this);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ tryNotifyMonthSet();
+ }
+
+ private void tryNotifyMonthSet() {
+ if (mCallBack != null) {
+ mMonthPicker.clearFocus();
+ mCallBack.onMonthSet(mMonthPicker, mMonthPicker.getYear(),
+ mMonthPicker.getMonth());
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ if (Build.VERSION.SDK_INT >= 16) {
+ tryNotifyMonthSet();
+ }
+ super.onStop();
+ }
+
+ @Override
+ public void onMonthChanged(MonthPicker view, int year, int month) {
+ mMonthPicker.init(year, month, null);
+ }
+
+ /**
+ * Gets the {@link MonthPicker} contained in this dialog.
+ *
+ * @return The calendar view.
+ */
+ public MonthPicker getMonthPicker() {
+ return mMonthPicker;
+ }
+
+ /**
+ * Sets the current date.
+ *
+ * @param year The date year.
+ * @param monthOfYear The date month.
+ */
+ public void updateDate(int year, int monthOfYear) {
+ mMonthPicker.updateMonth(year, monthOfYear);
+ }
+
+ @Override
+ public Bundle onSaveInstanceState() {
+ Bundle state = super.onSaveInstanceState();
+ state.putInt(YEAR, mMonthPicker.getYear());
+ state.putInt(MONTH, mMonthPicker.getMonth());
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ int year = savedInstanceState.getInt(YEAR);
+ int month = savedInstanceState.getInt(MONTH);
+ mMonthPicker.init(year, month, this);
+ }
+}