Unbundle DatePicker

Bug: 18777272
Change-Id: I2be6e5db694e5bfe2487f9bb87101756248dbc0c
diff --git a/src/com/android/contacts/datepicker/DatePicker.java b/src/com/android/contacts/datepicker/DatePicker.java
index 1b3b807..c6708a1 100644
--- a/src/com/android/contacts/datepicker/DatePicker.java
+++ b/src/com/android/contacts/datepicker/DatePicker.java
@@ -16,13 +16,8 @@
 
 package com.android.contacts.datepicker;
 
-// This is a fork of the standard Android DatePicker that additionally allows toggling the year
-// on/off. It uses some private API so that not everything has to be copied.
-
 import android.animation.LayoutTransition;
-import android.annotation.Widget;
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.format.DateFormat;
@@ -41,13 +36,13 @@
 import com.android.contacts.R;
 
 import java.text.DateFormatSymbols;
-import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 
-import libcore.icu.ICU;
-
 /**
+ * This is a fork of the standard Android DatePicker that additionally allows toggling the year
+ * on/off.
+ *
  * A view for selecting a month / year / day based on a calendar like layout.
  *
  * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker
@@ -55,13 +50,13 @@
  *
  * For a dialog using this view, see {@link android.app.DatePickerDialog}.
  */
-@Widget
 public class DatePicker extends FrameLayout {
     /** Magic year that represents "no year" */
     public static int NO_YEAR = 0;
 
     private static final int DEFAULT_START_YEAR = 1900;
     private static final int DEFAULT_END_YEAR = 2100;
+    private static final TwoDigitFormatter sTwoDigitFormatter = new TwoDigitFormatter();
 
     /* UI Components */
     private final LinearLayout mPickerContainer;
@@ -113,7 +108,7 @@
 
         mPickerContainer = (LinearLayout) findViewById(R.id.parent);
         mDayPicker = (NumberPicker) findViewById(R.id.day);
-        mDayPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
+        mDayPicker.setFormatter(sTwoDigitFormatter);
         mDayPicker.setOnLongPressUpdateInterval(100);
         mDayPicker.setOnValueChangedListener(new OnValueChangeListener() {
             @Override
@@ -123,7 +118,7 @@
             }
         });
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
-        mMonthPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
+        mMonthPicker.setFormatter(sTwoDigitFormatter);
         DateFormatSymbols dfs = new DateFormatSymbols();
         String[] months = dfs.getShortMonths();
 
diff --git a/src/com/android/contacts/datepicker/ICU.java b/src/com/android/contacts/datepicker/ICU.java
new file mode 100644
index 0000000..229fda6
--- /dev/null
+++ b/src/com/android/contacts/datepicker/ICU.java
@@ -0,0 +1,51 @@
+package com.android.contacts.datepicker;
+
+public class ICU {
+
+    /**
+     * This method is directly copied from {@link libcore.icu.ICU}. The method is simple enough
+     * that it probably won't change.
+     */
+    public static char[] getDateFormatOrder(String pattern) {
+        char[] result = new char[3];
+        int resultIndex = 0;
+        boolean sawDay = false;
+        boolean sawMonth = false;
+        boolean sawYear = false;
+
+        for (int i = 0; i < pattern.length(); ++i) {
+            char ch = pattern.charAt(i);
+            if (ch == 'd' || ch == 'L' || ch == 'M' || ch == 'y') {
+                if (ch == 'd' && !sawDay) {
+                    result[resultIndex++] = 'd';
+                    sawDay = true;
+                } else if ((ch == 'L' || ch == 'M') && !sawMonth) {
+                    result[resultIndex++] = 'M';
+                    sawMonth = true;
+                } else if ((ch == 'y') && !sawYear) {
+                    result[resultIndex++] = 'y';
+                    sawYear = true;
+                }
+            } else if (ch == 'G') {
+                // Ignore the era specifier, if present.
+            } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
+                throw new IllegalArgumentException("Bad pattern character '"
+                        + ch + "' in " + pattern);
+            } else if (ch == '\'') {
+                if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '\'') {
+                    ++i;
+                } else {
+                    i = pattern.indexOf('\'', i + 1);
+                    if (i == -1) {
+                        throw new IllegalArgumentException("Bad quoting in " + pattern);
+                    }
+                    ++i;
+                }
+            } else {
+                // Ignore spaces and punctuation.
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/src/com/android/contacts/datepicker/TwoDigitFormatter.java b/src/com/android/contacts/datepicker/TwoDigitFormatter.java
new file mode 100644
index 0000000..7e03f28
--- /dev/null
+++ b/src/com/android/contacts/datepicker/TwoDigitFormatter.java
@@ -0,0 +1,55 @@
+package com.android.contacts.datepicker;
+
+import android.widget.NumberPicker;
+
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+/**
+ * Copy of {@link android.widget.NumberPicker.TwoDigitFormatter}, modified
+ * so that it doesn't use libcore.
+ *
+ * Use a custom NumberPicker formatting callback to use two-digit minutes
+ * strings like "01". Keeping a static formatter etc. is the most efficient
+ * way to do this; it avoids creating temporary objects on every call to
+ * format().
+ */
+public class TwoDigitFormatter implements NumberPicker.Formatter {
+    final StringBuilder mBuilder = new StringBuilder();
+
+    char mZeroDigit;
+    java.util.Formatter mFmt;
+
+    final Object[] mArgs = new Object[1];
+
+    public TwoDigitFormatter() {
+        final Locale locale = Locale.getDefault();
+        init(locale);
+    }
+
+    private void init(Locale locale) {
+        mFmt = createFormatter(locale);
+        mZeroDigit = getZeroDigit(locale);
+    }
+
+    public String format(int value) {
+        final Locale currentLocale = Locale.getDefault();
+        if (mZeroDigit != getZeroDigit(currentLocale)) {
+            init(currentLocale);
+        }
+        mArgs[0] = value;
+        mBuilder.delete(0, mBuilder.length());
+        mFmt.format("%02d", mArgs);
+        return mFmt.toString();
+    }
+
+    private static char getZeroDigit(Locale locale) {
+        // The original TwoDigitFormatter directly referenced LocaleData's value. Instead,
+        // we need to use the public DecimalFormatSymbols API.
+        return DecimalFormatSymbols.getInstance(locale).getZeroDigit();
+    }
+
+    private java.util.Formatter createFormatter(Locale locale) {
+        return new java.util.Formatter(mBuilder, locale);
+    }
+}