| @ -1,82 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import android.view.*; | |||
| import com.facebook.react.uimanager.*; | |||
| import net.time4j.android.*; | |||
| import android.content.*; | |||
| import android.support.annotation.*; | |||
| import com.facebook.react.uimanager.annotations.*; | |||
| import org.apache.commons.lang3.*; | |||
| import java.util.*; | |||
| import com.facebook.react.common.*; | |||
| public class DatePickerManager extends SimpleViewManager<View> | |||
| { | |||
| public static final String REACT_CLASS = "DatePickerManager"; | |||
| public static ThemedReactContext context; | |||
| public String getName() { | |||
| return "DatePickerManager"; | |||
| } | |||
| public PickerView createViewInstance(final ThemedReactContext reactContext) { | |||
| ApplicationStarter.initialize((Context)(DatePickerManager.context = reactContext), true); | |||
| return new PickerView(); | |||
| } | |||
| @ReactProp(name = "mode") | |||
| public void setMode(final PickerView view, @Nullable final String mode) { | |||
| try { | |||
| view.setMode(Mode.valueOf(mode)); | |||
| } | |||
| catch (Exception e) { | |||
| throw new IllegalArgumentException("Invalid mode. Valid modes: 'datetime', 'date', 'time'"); | |||
| } | |||
| } | |||
| @ReactProp(name = "date") | |||
| public void setDate(final PickerView view, @Nullable final double date) { | |||
| view.setDate(Utils.unixToDate(date)); | |||
| } | |||
| @ReactProp(name = "locale") | |||
| public void setLocale(final PickerView view, @Nullable final String locale) { | |||
| view.setLocale(LocaleUtils.toLocale(locale.replace('-', '_'))); | |||
| view.requestLayout(); | |||
| } | |||
| @ReactProp(name = "minimumDate") | |||
| public void setMinimumDate(final PickerView view, @Nullable final double date) { | |||
| view.setMinimumDate(Utils.unixToDate(date)); | |||
| } | |||
| @ReactProp(name = "maximumDate") | |||
| public void setMaximumDate(final PickerView view, @Nullable final double date) { | |||
| view.setMaximumDate(Utils.unixToDate(date)); | |||
| } | |||
| @ReactProp(name = "fadeToColor") | |||
| public void setFadeToColor(final PickerView view, @Nullable final String color) { | |||
| view.style.setFadeToColor(color); | |||
| } | |||
| @ReactProp(name = "textColor") | |||
| public void setTextColor(final PickerView view, @Nullable final String color) { | |||
| view.style.setTextColor(color); | |||
| } | |||
| @ReactProp(name = "minuteInterval") | |||
| public void setMinuteInterval(final PickerView view, @Nullable final int interval) throws Exception { | |||
| if (interval < 0 || interval > 59) { | |||
| throw new Exception("Minute interval out of bounds"); | |||
| } | |||
| if (interval > 1) { | |||
| view.setMinuteInterval(interval); | |||
| } | |||
| } | |||
| public Map getExportedCustomBubblingEventTypeConstants() { | |||
| return MapBuilder.builder().put((Object)"dateChange", (Object)MapBuilder.of((Object)"phasedRegistrationNames", (Object)MapBuilder.of((Object)"bubbled", (Object)"onChange"))).build(); | |||
| } | |||
| } | |||
| @ -1,38 +0,0 @@ | |||
| -ckage com.henninghall.date_picker.wheels; | |||
| import java.util.*; | |||
| import com.henninghall.date_picker.*; | |||
| public class DateWheel extends Wheel | |||
| { | |||
| public DateWheel(final PickerView pickerView, final int id) { | |||
| super(pickerView, id); | |||
| } | |||
| @Override | |||
| void init() { | |||
| final int maxDate = 31; | |||
| final int minDate = 1; | |||
| final Calendar cal = this.pickerView.getInitialDate(); | |||
| final String initialDate = this.format.format(cal.getTime()); | |||
| for (int i = minDate; i <= maxDate; ++i) { | |||
| final int currentDate = (Integer.valueOf(initialDate) + i) % maxDate + 1; | |||
| final String currentDateString = String.valueOf(currentDate); | |||
| this.values.add(currentDateString); | |||
| this.displayValues.add(currentDateString); | |||
| } | |||
| this.picker.setDisplayedValues((String[])this.displayValues.toArray(new String[0])); | |||
| this.picker.setMinValue(0); | |||
| this.picker.setMaxValue(maxDate - minDate); | |||
| } | |||
| @Override | |||
| public boolean visible() { | |||
| return this.pickerView.mode == Mode.date; | |||
| } | |||
| public String getFormatTemplate() { | |||
| return "d"; | |||
| } | |||
| } | |||
| @ -1,9 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| public enum Mode | |||
| { | |||
| date, | |||
| time, | |||
| datetime; | |||
| } | |||
| @ -1,38 +0,0 @@ | |||
| package com.henninghall.date_picker.wheels; | |||
| import java.text.*; | |||
| import java.util.*; | |||
| import com.henninghall.date_picker.*; | |||
| public class MonthWheel extends Wheel | |||
| { | |||
| public MonthWheel(final PickerView pickerView, final int id) { | |||
| super(pickerView, id); | |||
| } | |||
| @Override | |||
| void init() { | |||
| final int min = 0; | |||
| final int max = 12; | |||
| final Calendar cal = this.pickerView.getInitialDate(); | |||
| final SimpleDateFormat format = new SimpleDateFormat(this.getFormatTemplate(), this.pickerView.locale); | |||
| for (int i = min; i <= max; ++i) { | |||
| this.values.add(format.format(cal.getTime())); | |||
| this.displayValues.add(format.format(cal.getTime())); | |||
| cal.add(2, 1); | |||
| } | |||
| this.picker.setDisplayedValues((String[])this.displayValues.toArray(new String[0])); | |||
| this.picker.setMinValue(0); | |||
| this.picker.setMaxValue(max); | |||
| } | |||
| @Override | |||
| public boolean visible() { | |||
| return this.pickerView.mode == Mode.date; | |||
| } | |||
| public String getFormatTemplate() { | |||
| return "LLLL"; | |||
| } | |||
| } | |||
| @ -1,184 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import android.widget.*; | |||
| import cn.carbswang.android.numberpickerview.library.*; | |||
| import android.content.*; | |||
| import com.henninghall.date_picker.wheels.*; | |||
| import com.facebook.react.uimanager.events.*; | |||
| import java.text.*; | |||
| import com.facebook.react.bridge.*; | |||
| import android.view.*; | |||
| import android.os.*; | |||
| import org.apache.commons.lang3.time.*; | |||
| import com.henninghall.date_picker.wheelFunctions.*; | |||
| import java.util.*; | |||
| public class PickerView extends RelativeLayout | |||
| { | |||
| private final NumberPickerView hourPicker; | |||
| private final NumberPickerView ampmPicker; | |||
| private SimpleDateFormat dateFormat; | |||
| private HourWheel hourWheel; | |||
| private DayWheel dayWheel; | |||
| public MinutesWheel minutesWheel; | |||
| private AmPmWheel ampmWheel; | |||
| private Date minDate; | |||
| private Date maxDate; | |||
| public int minuteInterval; | |||
| public Locale locale; | |||
| public Mode mode; | |||
| public Style style; | |||
| WheelChangeListener onWheelChangeListener; | |||
| private final Runnable measureAndLayout; | |||
| public PickerView() { | |||
| super((Context)DatePickerManager.context); | |||
| this.minuteInterval = 1; | |||
| this.onWheelChangeListener = new WheelChangeListener() { | |||
| @Override | |||
| public void onChange(final Wheel wheel) { | |||
| final WritableMap event = Arguments.createMap(); | |||
| try { | |||
| final Date date = PickerView.this.dateFormat.parse(PickerView.this.getDateString()); | |||
| if (PickerView.this.minDate != null && date.before(PickerView.this.minDate)) { | |||
| PickerView.this.applyOnVisibleWheels(new AnimateToDate(PickerView.this.minDate)); | |||
| } | |||
| else if (PickerView.this.maxDate != null && date.after(PickerView.this.maxDate)) { | |||
| PickerView.this.applyOnVisibleWheels(new AnimateToDate(PickerView.this.maxDate)); | |||
| } | |||
| else { | |||
| event.putDouble("date", (double)date.getTime()); | |||
| ((RCTEventEmitter)DatePickerManager.context.getJSModule((Class)RCTEventEmitter.class)).receiveEvent(PickerView.this.getId(), "dateChange", event); | |||
| } | |||
| } | |||
| catch (ParseException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| }; | |||
| this.measureAndLayout = new Runnable() { | |||
| @Override | |||
| public void run() { | |||
| PickerView.this.measure(View.MeasureSpec.makeMeasureSpec(PickerView.this.getWidth(), 1073741824), View.MeasureSpec.makeMeasureSpec(PickerView.this.getHeight(), 1073741824)); | |||
| PickerView.this.layout(PickerView.this.getLeft(), PickerView.this.getTop(), PickerView.this.getRight(), PickerView.this.getBottom()); | |||
| } | |||
| }; | |||
| final View rootView = inflate(this.getContext(), R.layout.datepicker_view, (ViewGroup)this); | |||
| this.style = new Style(this); | |||
| final RelativeLayout wheelsWrapper = (RelativeLayout)rootView.findViewById(R.id.wheelsWrapper); | |||
| wheelsWrapper.setWillNotDraw(false); | |||
| this.locale = ((Build.VERSION.SDK_INT >= 21) ? Locale.forLanguageTag("en") : Locale.getDefault()); | |||
| final NumberPickerView dayPicker = (NumberPickerView)rootView.findViewById(R.id.day); | |||
| this.dayWheel = new DayWheel(dayPicker, this); | |||
| final NumberPickerView minutePicker = (NumberPickerView)rootView.findViewById(R.id.minutes); | |||
| this.minutesWheel = new MinutesWheel(minutePicker, this); | |||
| this.ampmPicker = (NumberPickerView)rootView.findViewById(R.id.ampm); | |||
| this.ampmWheel = new AmPmWheel(this.ampmPicker, this); | |||
| this.hourPicker = (NumberPickerView)rootView.findViewById(R.id.hour); | |||
| this.hourWheel = new HourWheel(this.hourPicker, this); | |||
| this.dateFormat = new SimpleDateFormat(this.getDateFormatTemplate(), Locale.US); | |||
| this.changeAmPmWhenPassingMidnightOrNoon(); | |||
| } | |||
| private void changeAmPmWhenPassingMidnightOrNoon() { | |||
| this.hourPicker.setOnValueChangeListenerInScrolling((NumberPickerView.OnValueChangeListenerInScrolling)new NumberPickerView.OnValueChangeListenerInScrolling() { | |||
| public void onValueChangeInScrolling(final NumberPickerView picker, final int oldVal, final int newVal) { | |||
| if (Utils.usesAmPm(PickerView.this.locale)) { | |||
| final String oldValue = PickerView.this.hourWheel.getValueAtIndex(oldVal); | |||
| final String newValue = PickerView.this.hourWheel.getValueAtIndex(newVal); | |||
| final boolean passingNoonOrMidnight = (oldValue.equals("12") && newValue.equals("11")) || (oldValue.equals("11") && newValue.equals("12")); | |||
| if (passingNoonOrMidnight) { | |||
| PickerView.this.ampmPicker.smoothScrollToValue((PickerView.this.ampmPicker.getValue() + 1) % 2, false); | |||
| } | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| public void setMinimumDate(final Date date) { | |||
| this.minDate = DateUtils.truncate(date, 12); | |||
| } | |||
| public void setMaximumDate(final Date date) { | |||
| this.maxDate = DateUtils.truncate(date, 12); | |||
| } | |||
| public void setDate(final Date date) { | |||
| this.applyOnAllWheels(new SetDate(date)); | |||
| } | |||
| public void setLocale(final Locale locale) { | |||
| this.locale = locale; | |||
| this.dateFormat = new SimpleDateFormat(this.getDateFormatTemplate(), Locale.US); | |||
| this.applyOnAllWheels(new Refresh()); | |||
| } | |||
| public void setMinuteInterval(final int interval) { | |||
| this.minuteInterval = interval; | |||
| this.applyOnVisibleWheels(new Refresh()); | |||
| } | |||
| public Calendar getInitialDate() { | |||
| final Calendar cal = Calendar.getInstance(); | |||
| if (this.minuteInterval <= 1) { | |||
| return cal; | |||
| } | |||
| final int exactMinute = Integer.valueOf(this.minutesWheel.format.format(cal.getTime())); | |||
| final int diffSinceLastInterval = exactMinute % this.minuteInterval; | |||
| final int diffAhead = this.minuteInterval - diffSinceLastInterval; | |||
| final int diffBehind = -diffSinceLastInterval; | |||
| final boolean closerToPrevious = this.minuteInterval / 2 > diffSinceLastInterval; | |||
| final int diffToExactValue = closerToPrevious ? diffBehind : diffAhead; | |||
| cal.add(12, diffToExactValue); | |||
| return (Calendar)cal.clone(); | |||
| } | |||
| private String getDateFormatTemplate() { | |||
| return this.dayWheel.getFormatTemplate() + " " + this.hourWheel.getFormatTemplate() + " " + this.minutesWheel.getFormatTemplate() + this.ampmWheel.getFormatTemplate(); | |||
| } | |||
| private String getDateString() { | |||
| return this.dayWheel.getValue() + " " + this.hourWheel.getValue() + " " + this.minutesWheel.getValue() + this.ampmWheel.getValue(); | |||
| } | |||
| public void setMode(final Mode mode) { | |||
| this.mode = mode; | |||
| this.applyOnAllWheels(new Refresh()); | |||
| } | |||
| public Collection<Wheel> getVisibleWheels() { | |||
| final Collection<Wheel> visibleWheels = new ArrayList<Wheel>(); | |||
| for (final Wheel wheel : this.getAllWheels()) { | |||
| if (wheel.visible()) { | |||
| visibleWheels.add(wheel); | |||
| } | |||
| } | |||
| return visibleWheels; | |||
| } | |||
| public List<Wheel> getAllWheels() { | |||
| return new ArrayList<Wheel>(Arrays.asList(this.dayWheel, this.hourWheel, this.minutesWheel, this.ampmWheel)); | |||
| } | |||
| public void applyOnAllWheels(final WheelFunction function) { | |||
| for (final Wheel wheel : this.getAllWheels()) { | |||
| function.apply(wheel); | |||
| } | |||
| } | |||
| public void applyOnVisibleWheels(final WheelFunction function) { | |||
| for (final Wheel wheel : this.getVisibleWheels()) { | |||
| function.apply(wheel); | |||
| } | |||
| } | |||
| public void requestLayout() { | |||
| super.requestLayout(); | |||
| this.post(this.measureAndLayout); | |||
| } | |||
| public WheelChangeListener getListener() { | |||
| return this.onWheelChangeListener; | |||
| } | |||
| } | |||
| @ -1,100 +0,0 @@ | |||
| package com.henninghall.date_picker.wheels; | |||
| import com.henninghall.date_picker.*; | |||
| import cn.carbswang.android.numberpickerview.library.*; | |||
| import java.text.*; | |||
| import java.util.*; | |||
| import org.apache.commons.lang3.*; | |||
| public abstract class Wheel | |||
| { | |||
| private final Wheel self; | |||
| public PickerView pickerView; | |||
| private String userSetValue; | |||
| ArrayList<String> values; | |||
| ArrayList<String> displayValues; | |||
| public NumberPickerView picker; | |||
| public SimpleDateFormat format; | |||
| SimpleDateFormat displayFormat; | |||
| abstract void init(); | |||
| public abstract boolean visible(); | |||
| abstract String getFormatTemplate(); | |||
| public Wheel(final NumberPickerView picker, final PickerView pickerView) { | |||
| this.self = this; | |||
| this.pickerView = pickerView; | |||
| this.picker = picker; | |||
| this.refresh(false); | |||
| picker.setOnValueChangedListener((NumberPickerView.OnValueChangeListener)new NumberPickerView.OnValueChangeListener() { | |||
| public void onValueChange(final NumberPickerView picker, final int oldVal, final int newVal) { | |||
| pickerView.getListener().onChange(Wheel.this.self); | |||
| } | |||
| }); | |||
| } | |||
| public int getIndexOfDate(final Date date) { | |||
| return this.values.indexOf(this.format.format(date)); | |||
| } | |||
| public void animateToDate(final Date date) { | |||
| this.picker.smoothScrollToValue(this.getIndexOfDate(date)); | |||
| } | |||
| public String getValue() { | |||
| if (!this.visible()) { | |||
| return this.userSetValue; | |||
| } | |||
| return this.getValueAtIndex(this.getIndex()); | |||
| } | |||
| public int getIndex() { | |||
| return this.picker.getValue(); | |||
| } | |||
| public String getValueAtIndex(final int index) { | |||
| return this.values.get(index); | |||
| } | |||
| public void setValue(final Date date) { | |||
| this.userSetValue = this.format.format(date); | |||
| final int index = this.getIndexOfDate(date); | |||
| if (index > -1) { | |||
| if (this.picker.getValue() == 0) { | |||
| this.picker.setValue(index); | |||
| } | |||
| else { | |||
| this.picker.smoothScrollToValue(index); | |||
| } | |||
| } | |||
| } | |||
| public void refresh(final boolean keepOldValue) { | |||
| this.displayFormat = new SimpleDateFormat(this.getFormatTemplate(), this.pickerView.locale); | |||
| this.format = new SimpleDateFormat(this.getFormatTemplate(), LocaleUtils.toLocale("en_US")); | |||
| this.values = new ArrayList<String>(); | |||
| this.displayValues = new ArrayList<String>(); | |||
| final int oldValue = this.picker.getValue(); | |||
| if (this.visible()) { | |||
| this.add(); | |||
| this.init(); | |||
| if (keepOldValue) { | |||
| this.picker.setValue(oldValue); | |||
| } | |||
| } | |||
| else { | |||
| this.remove(); | |||
| } | |||
| } | |||
| private void remove() { | |||
| this.picker.setVisibility(8); | |||
| } | |||
| private void add() { | |||
| this.picker.setVisibility(0); | |||
| } | |||
| } | |||
| @ -1,56 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import com.henninghall.date_picker.wheels.*; | |||
| import java.util.*; | |||
| import android.widget.*; | |||
| import android.os.*; | |||
| import android.view.*; | |||
| public class WheelOrderUpdater | |||
| { | |||
| private final PickerView pickerView; | |||
| WheelOrderUpdater(final PickerView v) { | |||
| this.pickerView = v; | |||
| } | |||
| public void update(final Locale locale, final Mode mode) { | |||
| if (mode != Mode.date) { | |||
| return; | |||
| } | |||
| final String ymdPattern = Utils.localeToYmdPattern(locale); | |||
| final ArrayList<Wheel> wheelOrder = this.ymdPatternToWheelOrder(ymdPattern); | |||
| this.placeWheelRightOf(wheelOrder.get(0), wheelOrder.get(1)); | |||
| this.placeWheelRightOf(wheelOrder.get(1), wheelOrder.get(2)); | |||
| } | |||
| private void placeWheelRightOf(final Wheel leftWheel, final Wheel rightWheel) { | |||
| final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(-2, Utils.getWheelHeight((View)this.pickerView)); | |||
| params.addRule(1, leftWheel.id); | |||
| if (Build.VERSION.SDK_INT >= 17) { | |||
| params.addRule(17, leftWheel.id); | |||
| } | |||
| rightWheel.picker.setLayoutParams((ViewGroup.LayoutParams)params); | |||
| } | |||
| private ArrayList<Wheel> ymdPatternToWheelOrder(final String ymdPattern) { | |||
| final String[] parts = ymdPattern.split("/"); | |||
| final ArrayList<Wheel> wheelList = new ArrayList<Wheel>(); | |||
| for (final String s : parts) { | |||
| switch (s.charAt(0)) { | |||
| case 'y': { | |||
| wheelList.add(this.pickerView.yearWheel); | |||
| } | |||
| case 'M': { | |||
| wheelList.add(this.pickerView.monthWheel); | |||
| } | |||
| case 'd': { | |||
| wheelList.add(this.pickerView.dateWheel); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return wheelList; | |||
| } | |||
| } | |||
| @ -1,58 +0,0 @@ | |||
| package com.henninghall.date_picker.wheels; | |||
| import java.util.*; | |||
| import com.henninghall.date_picker.*; | |||
| public class YearWheel extends Wheel | |||
| { | |||
| private int defaultStartYear; | |||
| private int defaultEndYear; | |||
| public YearWheel(final PickerView pickerView, final int id) { | |||
| super(pickerView, id); | |||
| this.defaultStartYear = 0; | |||
| this.defaultEndYear = 2100; | |||
| } | |||
| @Override | |||
| void init() { | |||
| final int startYear = this.getStartYear(); | |||
| final int endYear = this.getEndYear(); | |||
| for (int i = startYear; i <= endYear; ++i) { | |||
| this.values.add(String.valueOf(i)); | |||
| this.displayValues.add(String.valueOf(i)); | |||
| } | |||
| this.picker.setDisplayedValues((String[])this.displayValues.toArray(new String[0])); | |||
| final int year = Calendar.getInstance().get(1); | |||
| this.picker.setMinValue(startYear); | |||
| this.picker.setMaxValue(endYear); | |||
| } | |||
| private int getEndYear() { | |||
| if (this.pickerView.maxDate == null) { | |||
| return this.defaultEndYear; | |||
| } | |||
| final Calendar cal = Calendar.getInstance(); | |||
| cal.setTime(this.pickerView.maxDate); | |||
| return cal.get(1); | |||
| } | |||
| private int getStartYear() { | |||
| if (this.pickerView.minDate != null) { | |||
| final Calendar cal = Calendar.getInstance(); | |||
| cal.setTime(this.pickerView.minDate); | |||
| return cal.get(1); | |||
| } | |||
| return this.defaultStartYear; | |||
| } | |||
| @Override | |||
| public boolean visible() { | |||
| return this.pickerView.mode == Mode.date; | |||
| } | |||
| public String getFormatTemplate() { | |||
| return "y"; | |||
| } | |||
| } | |||