| Index: content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java
|
| diff --git a/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java b/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cbcb3654074da85520840b233d98b60d92f93e36
|
| --- /dev/null
|
| +++ b/content/public/android/java/src/org/chromium/content/browser/input/WeekPicker.java
|
| @@ -0,0 +1,330 @@
|
| +// 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.input;
|
| +
|
| +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.NumberPicker;
|
| +import android.widget.NumberPicker.OnValueChangeListener;
|
| +
|
| +import java.text.DateFormatSymbols;
|
| +import java.util.Arrays;
|
| +import java.util.Calendar;
|
| +import java.util.Locale;
|
| +
|
| +import org.chromium.content.R;
|
| +
|
| +// This class is heavily based on android.widget.DatePicker.
|
| +public class WeekPicker extends BaseDatePicker {
|
| +
|
| + private final NumberPicker mWeekSpinner;
|
| +
|
| + private final NumberPicker mYearSpinner;
|
| +
|
| + private OnWeekChangedListener mWeekChangedListener;
|
| +
|
| + /**
|
| + * The callback used to indicate the user changes\d the date.
|
| + */
|
| + public interface OnWeekChangedListener {
|
| +
|
| + /**
|
| + * Called upon a date change.
|
| + *
|
| + * @param view The view associated with this listener.
|
| + * @param year The year that was set.
|
| + * @param weekOfYear The week in year.
|
| + */
|
| + void onWeekChanged(WeekPicker view, int year, int weekOfYear);
|
| + }
|
| +
|
| + public WeekPicker(Context context) {
|
| + this(context, null);
|
| + }
|
| +
|
| + public WeekPicker(Context context, AttributeSet attrs) {
|
| + this(context, attrs, android.R.attr.datePickerStyle);
|
| + }
|
| +
|
| + public WeekPicker(Context context, AttributeSet attrs, int defStyle) {
|
| + super(context, attrs, defStyle);
|
| +
|
| + LayoutInflater inflater = (LayoutInflater) context
|
| + .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
| + inflater.inflate(R.layout.week_picker, this, true);
|
| +
|
| + OnValueChangeListener onChangeListener = new OnValueChangeListener() {
|
| + @Override
|
| + public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
|
| + // take care of wrapping of weeks to update greater fields
|
| + if (picker == mWeekSpinner) {
|
| + Calendar tempDate = (Calendar) mCurrentDate.clone();
|
| + if (oldVal == mWeekSpinner.getMaxValue()
|
| + && newVal == mWeekSpinner.getMinValue()) {
|
| + tempDate.add(Calendar.WEEK_OF_YEAR, 1);
|
| + } else if (oldVal == mWeekSpinner.getMinValue()
|
| + && newVal == mWeekSpinner.getMaxValue()) {
|
| + tempDate.add(Calendar.WEEK_OF_YEAR, -1);
|
| + } else {
|
| + tempDate.add(Calendar.WEEK_OF_YEAR, newVal - oldVal);
|
| + }
|
| + // now set the date to the adjusted one
|
| + setDate(getISOWeekYearForDate(tempDate),
|
| + getWeekForDate(tempDate));
|
| + } else if (picker == mYearSpinner) {
|
| + setDate(newVal, getWeekForDate(mCurrentDate));
|
| + } else {
|
| + throw new IllegalArgumentException();
|
| + }
|
| +
|
| + updateSpinners();
|
| + notifyDateChanged();
|
| + }
|
| + };
|
| +
|
| + // week
|
| + mWeekSpinner = (NumberPicker) findViewById(R.id.week);
|
| + mWeekSpinner.setOnLongPressUpdateInterval(200);
|
| + mWeekSpinner.setOnValueChangedListener(onChangeListener);
|
| +
|
| + // year
|
| + mYearSpinner = (NumberPicker) findViewById(R.id.year);
|
| + mYearSpinner.setOnLongPressUpdateInterval(100);
|
| + mYearSpinner.setOnValueChangedListener(onChangeListener);
|
| +
|
| + // initialize to current date
|
| + mCurrentDate.setTimeInMillis(System.currentTimeMillis());
|
| + init(getISOWeekYearForDate(mCurrentDate), getWeekForDate(mCurrentDate), null);
|
| + }
|
| +
|
| + @Override
|
| + public void setEnabled(boolean enabled) {
|
| + if (mIsEnabled == enabled) {
|
| + return;
|
| + }
|
| + super.setEnabled(enabled);
|
| + mWeekSpinner.setEnabled(enabled);
|
| + mYearSpinner.setEnabled(enabled);
|
| + }
|
| +
|
| + @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);
|
| + }
|
| +
|
| + /**
|
| + * Updates the current date.
|
| + *
|
| + * @param year The year.
|
| + * @param week The week in year.
|
| + */
|
| + public void updateWeek(int year, int week) {
|
| + if (!isNewDate(year, week)) {
|
| + return;
|
| + }
|
| + setDate(year, week);
|
| + 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(), getWeek());
|
| + }
|
| +
|
| + @Override
|
| + protected void onRestoreInstanceState(Parcelable state) {
|
| + SavedState ss = (SavedState) state;
|
| + super.onRestoreInstanceState(ss.getSuperState());
|
| + setDate(ss.mYear, ss.mWeek);
|
| + updateSpinners();
|
| + }
|
| +
|
| + /**
|
| + * Initialize the state. If the provided values designate an inconsistent
|
| + * date the values are normalized before updating the spinners.
|
| + *
|
| + * @param year The initial week year.
|
| + * @param weekOfYear The initial week in year.
|
| + * @param onWeekChangedListener How user is notified date is changed by
|
| + * user, can be null.
|
| + */
|
| + public void init(int year, int weekOfYear, OnWeekChangedListener onWeekChangedListener) {
|
| + setDate(year, weekOfYear);
|
| + updateSpinners();
|
| + mWeekChangedListener = onWeekChangedListener;
|
| + }
|
| +
|
| + private boolean isNewDate(int year, int week) {
|
| + return (getYear() != year || getWeek() != week);
|
| + }
|
| +
|
| + private Calendar createDateFromWeek(int year, int week) {
|
| + Calendar date = getCalendarForLocale(null, mCurrentLocale);
|
| + date.set(Calendar.YEAR, year);
|
| + date.set(Calendar.WEEK_OF_YEAR, week);
|
| + return date;
|
| + }
|
| +
|
| + public static int getISOWeekYearForDate(Calendar date) {
|
| + int year = date.get(Calendar.YEAR);
|
| + int month = date.get(Calendar.MONTH);
|
| + int week = date.get(Calendar.WEEK_OF_YEAR);
|
| + if (month == 0 && week > 51) {
|
| + year--;
|
| + } else if (month == 11 && week == 1) {
|
| + year++;
|
| + }
|
| + return year;
|
| + }
|
| +
|
| + public static int getWeekForDate(Calendar date) {
|
| + return date.get(Calendar.WEEK_OF_YEAR);
|
| + }
|
| +
|
| + private void setDate(int year, int week) {
|
| + mCurrentDate = createDateFromWeek(year, week);
|
| + if (mCurrentDate.before(mMinDate)) {
|
| + mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
|
| + } else if (mCurrentDate.after(mMaxDate)) {
|
| + mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
|
| + }
|
| + }
|
| +
|
| + private int getNumberOfWeeks() {
|
| + // Create a date in the middle of the year, where the week year matches the year.
|
| + Calendar date = createDateFromWeek(getYear(), 20);
|
| + return date.getActualMaximum(Calendar.WEEK_OF_YEAR);
|
| + }
|
| +
|
| + private void updateSpinners() {
|
| + // set the spinner ranges respecting the min and max dates
|
| + if (mCurrentDate.equals(mMinDate)) {
|
| + mWeekSpinner.setMinValue(getWeekForDate(mCurrentDate));
|
| + mWeekSpinner.setMaxValue(getNumberOfWeeks());
|
| + mWeekSpinner.setWrapSelectorWheel(false);
|
| + } else if (mCurrentDate.equals(mMaxDate)) {
|
| + mWeekSpinner.setMinValue(getNumberOfWeeks());
|
| + mWeekSpinner.setMaxValue(getWeekForDate(mCurrentDate));
|
| + mWeekSpinner.setWrapSelectorWheel(false);
|
| + } else {
|
| + mWeekSpinner.setMinValue(1);
|
| + mWeekSpinner.setMaxValue(getNumberOfWeeks());
|
| + mWeekSpinner.setWrapSelectorWheel(true);
|
| + }
|
| +
|
| + // year spinner range does not change based on the current date
|
| + mYearSpinner.setMinValue(getISOWeekYearForDate(mMinDate));
|
| + mYearSpinner.setMaxValue(getISOWeekYearForDate(mMaxDate));
|
| + mYearSpinner.setWrapSelectorWheel(false);
|
| +
|
| + // set the spinner values
|
| + mYearSpinner.setValue(getISOWeekYearForDate(mCurrentDate));
|
| + mWeekSpinner.setValue(getWeekForDate(mCurrentDate));
|
| + }
|
| +
|
| + /**
|
| + * @return The selected year.
|
| + */
|
| + public int getYear() {
|
| + return getISOWeekYearForDate(mCurrentDate);
|
| + }
|
| +
|
| + /**
|
| + * @return The selected week.
|
| + */
|
| + public int getWeek() {
|
| + return getWeekForDate(mCurrentDate);
|
| + }
|
| +
|
| + /**
|
| + * Notifies the listener, if such, for a change in the selected date.
|
| + */
|
| + private void notifyDateChanged() {
|
| + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
|
| + if (mWeekChangedListener != null) {
|
| + mWeekChangedListener.onWeekChanged(this, getYear(), getWeek());
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Class for managing state storing/restoring.
|
| + */
|
| + private static class SavedState extends BaseSavedState {
|
| +
|
| + private final int mYear;
|
| +
|
| + private final int mWeek;
|
| +
|
| + /**
|
| + * Constructor called from {@link DatePicker#onSaveInstanceState()}
|
| + */
|
| + private SavedState(Parcelable superState, int year, int week) {
|
| + super(superState);
|
| + mYear = year;
|
| + mWeek = week;
|
| + }
|
| +
|
| + /**
|
| + * Constructor called from {@link #CREATOR}
|
| + */
|
| + private SavedState(Parcel in) {
|
| + super(in);
|
| + mYear = in.readInt();
|
| + mWeek = in.readInt();
|
| + }
|
| +
|
| + @Override
|
| + public void writeToParcel(Parcel dest, int flags) {
|
| + super.writeToParcel(dest, flags);
|
| + dest.writeInt(mYear);
|
| + dest.writeInt(mWeek);
|
| + }
|
| +
|
| + @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];
|
| + }
|
| + };
|
| + }
|
| +}
|
|
|