Improved architecturemaster
| @ -1,42 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import java.util.HashMap; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| public class EmptyWheelUpdater { | |||
| private final PickerView pickerView; | |||
| private final HashMap<Integer, NumberPickerView> views; | |||
| EmptyWheelUpdater(PickerView pickerView) { | |||
| this.pickerView = pickerView; | |||
| this.views = getViews(); | |||
| } | |||
| private HashMap<Integer, NumberPickerView> getViews() { | |||
| HashMap<Integer, NumberPickerView> views = new HashMap<>(); | |||
| for (int id: Utils.emptyWheelIds) { | |||
| NumberPickerView view = (NumberPickerView) pickerView.findViewById(id); | |||
| views.put(id, view); | |||
| } | |||
| return views; | |||
| } | |||
| void update() { | |||
| hideAll(); | |||
| int numberOfVisibleWheels = pickerView.getVisibleWheels().size(); | |||
| int emptyViewsToAdd = numberOfVisibleWheels + 1; | |||
| for (int i = 0; i < emptyViewsToAdd; i++) { | |||
| int index = i * 2; | |||
| pickerView.wheelsWrapper.addView(views.get(Utils.emptyWheelIds[i]), index); | |||
| } | |||
| } | |||
| private void hideAll() { | |||
| for (NumberPickerView view: views.values()) { | |||
| pickerView.wheelsWrapper.removeView(view); | |||
| } | |||
| } | |||
| } | |||
| @ -1,12 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import android.text.format.DateFormat; | |||
| public class Settings { | |||
| public static boolean usesAmPm (){ | |||
| return !DateFormat.is24HourFormat(DatePickerManager.context); | |||
| } | |||
| } | |||
| @ -0,0 +1,206 @@ | |||
| package com.henninghall.date_picker; | |||
| import android.util.Log; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| import com.henninghall.date_picker.models.Mode; | |||
| import com.henninghall.date_picker.models.WheelType; | |||
| import com.henninghall.date_picker.props.DateProp; | |||
| import com.henninghall.date_picker.props.FadeToColorProp; | |||
| import com.henninghall.date_picker.props.HeightProp; | |||
| import com.henninghall.date_picker.props.LocaleProp; | |||
| import com.henninghall.date_picker.props.MaximumDateProp; | |||
| import com.henninghall.date_picker.props.MinimumDateProp; | |||
| import com.henninghall.date_picker.props.MinuteIntervalProp; | |||
| import com.henninghall.date_picker.props.ModeProp; | |||
| import com.henninghall.date_picker.props.Prop; | |||
| import com.henninghall.date_picker.props.TextColorProp; | |||
| import com.henninghall.date_picker.props.UtcProp; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.Calendar; | |||
| import java.util.HashMap; | |||
| import java.util.Locale; | |||
| import java.util.TimeZone; | |||
| public class State { | |||
| private final Prop dateProp = new DateProp(); | |||
| private final Prop modeProp = new ModeProp(); | |||
| private final Prop localeProp = new LocaleProp(); | |||
| private final Prop fadeToColorProp = new FadeToColorProp(); | |||
| private final Prop textColorProp = new TextColorProp(); | |||
| private final Prop minuteIntervalProp = new MinuteIntervalProp(); | |||
| private final Prop minimumDateProp = new MinimumDateProp(); | |||
| private final Prop maximumDateProp = new MaximumDateProp(); | |||
| private final Prop utcProp = new UtcProp(); | |||
| private final Prop heightProp = new HeightProp(); | |||
| private final HashMap props = new HashMap<String, Prop>() {{ | |||
| put(DateProp.name, dateProp); | |||
| put(ModeProp.name, modeProp); | |||
| put(LocaleProp.name, localeProp); | |||
| put(FadeToColorProp.name, fadeToColorProp); | |||
| put(TextColorProp.name, textColorProp); | |||
| put(MinuteIntervalProp.name, minuteIntervalProp); | |||
| put(MinimumDateProp.name, minimumDateProp); | |||
| put(MaximumDateProp.name, maximumDateProp); | |||
| put(UtcProp.name, utcProp); | |||
| }}; | |||
| private Prop getProp(String name){ | |||
| return (Prop) props.get(name); | |||
| } | |||
| void setProp(String propName, Dynamic value){ | |||
| getProp(propName).setValue(value); | |||
| } | |||
| public Mode getMode() { | |||
| return (Mode) modeProp.getValue(); | |||
| } | |||
| public String getFadeToColor() { | |||
| return (String) fadeToColorProp.getValue(); | |||
| } | |||
| public String getTextColor() { | |||
| return (String) textColorProp.getValue(); | |||
| } | |||
| public int getMinuteInterval() { | |||
| return (int) minuteIntervalProp.getValue(); | |||
| } | |||
| public Locale getLocale() { | |||
| return (Locale) localeProp.getValue(); | |||
| } | |||
| public Calendar getMinimumDate(){ | |||
| DateBoundary db = new DateBoundary(getTimeZone(), (String) minimumDateProp.getValue()); | |||
| return db.get(); | |||
| } | |||
| public Calendar getMaximumDate(){ | |||
| DateBoundary db = new DateBoundary(getTimeZone(), (String) maximumDateProp.getValue()); | |||
| return db.get(); | |||
| } | |||
| public TimeZone getTimeZone(){ | |||
| boolean utc = (boolean) utcProp.getValue(); | |||
| return utc ? TimeZone.getTimeZone("UTC") : TimeZone.getDefault(); | |||
| } | |||
| public Calendar getDate() { | |||
| String date = (String) dateProp.getValue(); | |||
| return Utils.isoToCalendar(date, getTimeZone()); | |||
| } | |||
| public Integer getHeight() { | |||
| return (Integer) heightProp.getValue(); | |||
| } | |||
| public int getShownCount() { | |||
| int DP_PER_SHOW_SHOW_COUNT = 35; | |||
| int showCount = getHeight() / DP_PER_SHOW_SHOW_COUNT; | |||
| int oddShowCount = showCount % 2 == 0 ? showCount + 1 : showCount; | |||
| return oddShowCount; | |||
| } | |||
| public ArrayList<WheelType> getOrderedWheels() { | |||
| String dateTimePattern = LocaleUtils.getDateTimePattern(getLocale()); | |||
| ArrayList<WheelType> unorderedTypes = new ArrayList(Arrays.asList(WheelType.values())); | |||
| ArrayList<WheelType> orderedWheels = new ArrayList<>(); | |||
| // Always put day wheel first | |||
| unorderedTypes.remove(WheelType.DAY); | |||
| orderedWheels.add(WheelType.DAY); | |||
| for (char ch : dateTimePattern.toCharArray()){ | |||
| try { | |||
| WheelType wheelType = Utils.patternCharToWheelType(ch); | |||
| if (unorderedTypes.contains(wheelType)) { | |||
| unorderedTypes.remove(wheelType); | |||
| orderedWheels.add(wheelType); | |||
| } | |||
| } catch (Exception e) { | |||
| // ignore unknown pattern chars that not correspond to any wheel type | |||
| } | |||
| } | |||
| // If AM/PM wheel remains it means that the locale does not have AM/PM by default and it | |||
| // should be put last. | |||
| if(unorderedTypes.contains(WheelType.AM_PM)){ | |||
| unorderedTypes.remove(WheelType.AM_PM); | |||
| orderedWheels.add(WheelType.AM_PM); | |||
| } | |||
| if(!unorderedTypes.isEmpty()) { | |||
| Log.e( | |||
| "RNDatePicker", | |||
| unorderedTypes.size() + " wheel types cannot be ordered. Wheel type 0: " + unorderedTypes.get(0)); | |||
| } | |||
| return orderedWheels; | |||
| } | |||
| public ArrayList<WheelType> getVisibleWheels() { | |||
| ArrayList<WheelType> visibleWheels = new ArrayList<>(); | |||
| Mode mode = getMode(); | |||
| switch (mode){ | |||
| case datetime: { | |||
| visibleWheels.add(WheelType.DAY); | |||
| visibleWheels.add(WheelType.HOUR); | |||
| visibleWheels.add(WheelType.MINUTE); | |||
| break; | |||
| } | |||
| case time: { | |||
| visibleWheels.add(WheelType.HOUR); | |||
| visibleWheels.add(WheelType.MINUTE); | |||
| break; | |||
| } | |||
| case date: { | |||
| visibleWheels.add(WheelType.YEAR); | |||
| visibleWheels.add(WheelType.MONTH); | |||
| visibleWheels.add(WheelType.DATE); | |||
| break; | |||
| } | |||
| } | |||
| if((mode == Mode.time || mode == Mode.datetime) && Utils.usesAmPm()){ | |||
| visibleWheels.add(WheelType.AM_PM); | |||
| } | |||
| return visibleWheels; | |||
| } | |||
| public ArrayList<WheelType> getOrderedVisibleWheels() { | |||
| ArrayList<WheelType> orderedWheels = getOrderedWheels(); | |||
| ArrayList<WheelType> visibleWheels = getVisibleWheels(); | |||
| ArrayList<WheelType> visibleOrderedWheels = new ArrayList<>(); | |||
| for (WheelType wheel : orderedWheels){ | |||
| if(visibleWheels.contains(wheel)) visibleOrderedWheels.add(wheel); | |||
| } | |||
| return visibleOrderedWheels; | |||
| } | |||
| // Rounding cal to closest minute interval | |||
| public Calendar getInitialDate() { | |||
| Calendar cal = Calendar.getInstance(); | |||
| int minuteInterval = getMinuteInterval(); | |||
| if(minuteInterval <= 1) return cal; | |||
| SimpleDateFormat minuteFormat = new SimpleDateFormat("mm", getLocale()); | |||
| int exactMinute = Integer.valueOf(minuteFormat.format(cal.getTime())); | |||
| int diffSinceLastInterval = exactMinute % minuteInterval; | |||
| int diffAhead = minuteInterval - diffSinceLastInterval; | |||
| int diffBehind= -diffSinceLastInterval; | |||
| boolean closerToPrevious = minuteInterval / 2 > diffSinceLastInterval; | |||
| int diffToExactValue = closerToPrevious ? diffBehind : diffAhead; | |||
| cal.add(Calendar.MINUTE, diffToExactValue); | |||
| return (Calendar) cal.clone(); | |||
| } | |||
| public WheelType getVisibleWheel(int index) { | |||
| return getOrderedVisibleWheels().get(index); | |||
| } | |||
| } | |||
| @ -1,61 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import android.graphics.Color; | |||
| import android.graphics.drawable.GradientDrawable; | |||
| import android.widget.ImageView; | |||
| import com.henninghall.date_picker.wheelFunctions.SetShowCount; | |||
| import com.henninghall.date_picker.wheelFunctions.TextColor; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| class Style { | |||
| private static int DP_PER_SHOW_SHOW_COUNT = 35; | |||
| private final GradientDrawable gradientBottom; | |||
| private final GradientDrawable gradientTop; | |||
| private final PickerView pickerView; | |||
| public Style(PickerView pickerView) { | |||
| this.pickerView = pickerView; | |||
| ImageView overlayTop = (ImageView) pickerView.findViewById(R.id.overlay_top); | |||
| ImageView overlayBottom = (ImageView) pickerView.findViewById(R.id.overlay_bottom); | |||
| this.gradientTop = (GradientDrawable) overlayTop.getDrawable(); | |||
| this.gradientBottom = (GradientDrawable) overlayBottom.getDrawable(); | |||
| } | |||
| public void setFadeToColor(String color) { | |||
| int alpha = validColor(color) ? 255 : 0; | |||
| gradientTop.setAlpha(alpha); | |||
| gradientBottom.setAlpha(alpha); | |||
| if(validColor(color)) { | |||
| int startColor = Color.parseColor("#FF"+ color.substring(1)); | |||
| int endColor = Color.parseColor("#00" + color.substring(1)); | |||
| gradientTop.setColors(new int[] {startColor, endColor}); | |||
| gradientBottom.setColors(new int[] {startColor, endColor}); | |||
| } | |||
| } | |||
| public void setTextColor(String color) { | |||
| this.pickerView.applyOnAllWheels(new TextColor(color)); | |||
| } | |||
| public void setHeight(int height) { | |||
| int showCount = height / DP_PER_SHOW_SHOW_COUNT; | |||
| int oddShowCount = showCount % 2 == 0 ? showCount + 1 : showCount; | |||
| pickerView.applyOnAllWheels(new SetShowCount(oddShowCount)); | |||
| setShownCountOnEmptyWheels(oddShowCount); | |||
| } | |||
| private void setShownCountOnEmptyWheels(int shownCount) { | |||
| for (int id : Utils.emptyWheelIds) { | |||
| NumberPickerView view = (NumberPickerView) pickerView.findViewById(id); | |||
| if(view != null) view.setShownCount(shownCount); | |||
| } | |||
| } | |||
| private boolean validColor(String color){ | |||
| return color != null && color.length() == 7; | |||
| } | |||
| } | |||
| @ -1,56 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import com.facebook.react.bridge.Arguments; | |||
| import com.facebook.react.bridge.WritableMap; | |||
| import com.facebook.react.uimanager.events.RCTEventEmitter; | |||
| import com.henninghall.date_picker.wheelFunctions.AnimateToDate; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import java.text.DateFormat; | |||
| import java.text.FieldPosition; | |||
| import java.text.ParseException; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| import java.util.Date; | |||
| import java.util.Locale; | |||
| import java.util.TimeZone; | |||
| public class WheelChangeListenerImpl implements WheelChangeListener { | |||
| private final PickerView pickerView; | |||
| public WheelChangeListenerImpl(PickerView pickerView) { | |||
| this.pickerView = pickerView; | |||
| } | |||
| @Override | |||
| public void onChange(Wheel picker) { | |||
| WritableMap event = Arguments.createMap(); | |||
| TimeZone timeZone = pickerView.timeZone; | |||
| SimpleDateFormat dateFormat = pickerView.getDateFormat(); | |||
| Calendar minDate = pickerView.getMinimumDate(); | |||
| Calendar maxDate = pickerView.getMaximumDate(); | |||
| try { | |||
| dateFormat.setTimeZone(timeZone); | |||
| Calendar date = Calendar.getInstance(timeZone); | |||
| String toParse = this.pickerView.getDateString(); | |||
| Date newDate = dateFormat.parse(toParse); | |||
| date.setTime(newDate); | |||
| if (minDate != null && date.before(minDate)) pickerView.applyOnVisibleWheels( | |||
| new AnimateToDate(minDate) | |||
| ); | |||
| else if (maxDate != null && date.after(maxDate)) pickerView.applyOnVisibleWheels( | |||
| new AnimateToDate(maxDate) | |||
| ); | |||
| else { | |||
| event.putString("date", Utils.dateToIso(date)); | |||
| DatePickerManager.context.getJSModule(RCTEventEmitter.class).receiveEvent(pickerView.getId(), "dateChange", event); | |||
| } | |||
| } catch (ParseException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @ -1,109 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.HashMap; | |||
| import java.util.Locale; | |||
| public class WheelOrder | |||
| { | |||
| private final HashMap<WheelType, Wheel> wheelPerWheelType; | |||
| private PickerView pickerView; | |||
| private ArrayList<WheelType> orderedWheels; | |||
| WheelOrder(final PickerView view) { | |||
| this.pickerView = view; | |||
| this.wheelPerWheelType = new HashMap<WheelType, Wheel>() {{ | |||
| put(WheelType.DAY, pickerView.dayWheel); | |||
| put(WheelType.YEAR, pickerView.yearWheel); | |||
| put(WheelType.MONTH, pickerView.monthWheel); | |||
| put(WheelType.DATE, pickerView.dateWheel); | |||
| put(WheelType.HOUR, pickerView.hourWheel); | |||
| put(WheelType.MINUTE, pickerView.minutesWheel); | |||
| put(WheelType.AM_PM, pickerView.ampmWheel); | |||
| }}; | |||
| } | |||
| private void updateAllWheels(final Locale locale) { | |||
| try { | |||
| this.orderedWheels = getOrderedWheels(locale); | |||
| pickerView.wheelsWrapper.removeAllViews(); | |||
| for (int i = 0; i < wheelPerWheelType.size(); i++) { | |||
| Wheel w = getWheels(i); | |||
| if(w.visible()) { | |||
| pickerView.wheelsWrapper.addView(w.picker); | |||
| } | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| void update(final Locale locale) { | |||
| updateAllWheels(locale); | |||
| pickerView.emptyWheelUpdater.update(); | |||
| } | |||
| private Wheel getWheels(int index){ | |||
| return wheelPerWheelType.get(orderedWheels.get(index)); | |||
| } | |||
| Wheel getVisibleWheel(int index){ | |||
| return getVisibleWheels().get(index); | |||
| } | |||
| private ArrayList<Wheel> getVisibleWheels() { | |||
| ArrayList<Wheel> visibleOrderedWheels = new ArrayList<>(); | |||
| for (WheelType wheelType : orderedWheels){ | |||
| Wheel wheel = wheelPerWheelType.get(wheelType); | |||
| if(wheel.visible()) { | |||
| visibleOrderedWheels.add(wheel); | |||
| } | |||
| } | |||
| return visibleOrderedWheels; | |||
| } | |||
| private ArrayList<WheelType> getOrderedWheels(Locale locale) throws Exception { | |||
| String dateTimePattern = LocaleUtils.getDateTimePattern(locale); | |||
| ArrayList<WheelType> unorderedTypes = new ArrayList(Arrays.asList(WheelType.values())); | |||
| ArrayList<WheelType> orderedWheels = new ArrayList<>(); | |||
| // Always put day wheel first | |||
| unorderedTypes.remove(WheelType.DAY); | |||
| orderedWheels.add(WheelType.DAY); | |||
| for (char ch : dateTimePattern.toCharArray()){ | |||
| try { | |||
| WheelType wheelType = Utils.patternCharToWheelType(ch); | |||
| if (unorderedTypes.contains(wheelType)) { | |||
| unorderedTypes.remove(wheelType); | |||
| orderedWheels.add(wheelType); | |||
| } | |||
| } catch (Exception e) { | |||
| // ignore unknown pattern chars that not correspond to any wheel type | |||
| } | |||
| } | |||
| // If AM/PM wheel remains it means that the locale does not have AM/PM by default and it | |||
| // should be put last. | |||
| if(unorderedTypes.contains(WheelType.AM_PM)){ | |||
| unorderedTypes.remove(WheelType.AM_PM); | |||
| orderedWheels.add(WheelType.AM_PM); | |||
| } | |||
| if(!unorderedTypes.isEmpty()) { | |||
| throw new Exception(unorderedTypes.size() + " wheel types cannot be ordered. Wheel type 0: " + unorderedTypes.get(0)); | |||
| } | |||
| return orderedWheels; | |||
| } | |||
| } | |||
| @ -1,5 +0,0 @@ | |||
| package com.henninghall.date_picker; | |||
| public enum WheelPosition { | |||
| LEFT, RIGHT, MIDDLE | |||
| } | |||
| @ -1,4 +1,4 @@ | |||
| package com.henninghall.date_picker; | |||
| package com.henninghall.date_picker.models; | |||
| public enum Mode { | |||
| date, time, datetime | |||
| @ -1,4 +1,4 @@ | |||
| package com.henninghall.date_picker; | |||
| package com.henninghall.date_picker.models; | |||
| public enum WheelType { | |||
| DAY, DATE, MONTH, YEAR, HOUR, MINUTE, AM_PM | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public class DateProp extends Prop<String> { | |||
| public static final String name = "date"; | |||
| @Override | |||
| public String toValue(Dynamic value){ | |||
| return value.asString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public class FadeToColorProp extends Prop<String> { | |||
| public static final String name = "fadeToColor"; | |||
| @Override | |||
| public String toValue(Dynamic value){ | |||
| return value.asString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| import com.henninghall.date_picker.models.Mode; | |||
| public class HeightProp extends Prop<Integer> { | |||
| public static final String name = "height"; | |||
| @Override | |||
| public Integer toValue(Dynamic value){ | |||
| return value.asInt(); | |||
| } | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import android.os.Build; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| import org.apache.commons.lang3.LocaleUtils; | |||
| import java.util.Locale; | |||
| public class LocaleProp extends Prop<Locale> { | |||
| public static final String name = "locale"; | |||
| public LocaleProp(){ | |||
| super( | |||
| Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP | |||
| ? Locale.forLanguageTag("en") | |||
| : Locale.getDefault() | |||
| ); | |||
| } | |||
| @Override | |||
| public Locale toValue(Dynamic value){ | |||
| return LocaleUtils.toLocale(value.asString().replace('-','_')); | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public class MaximumDateProp extends Prop<String> { | |||
| public static final String name = "maximumDate"; | |||
| @Override | |||
| public String toValue(Dynamic value){ | |||
| return value.asString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public class MinimumDateProp extends Prop<String> { | |||
| public static final String name = "minimumDate"; | |||
| @Override | |||
| public String toValue(Dynamic value){ | |||
| return value.asString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,17 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| import com.henninghall.date_picker.models.Mode; | |||
| public class MinuteIntervalProp extends Prop<Integer> { | |||
| public static final String name = "minuteInterval"; | |||
| public MinuteIntervalProp(){ | |||
| super(1); | |||
| } | |||
| public Integer toValue(Dynamic value){ | |||
| return value.asInt(); | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| import com.henninghall.date_picker.models.Mode; | |||
| public class ModeProp extends Prop<Mode> { | |||
| public static final String name = "mode"; | |||
| @Override | |||
| public Mode toValue(Dynamic value){ | |||
| return Mode.valueOf(value.asString()); | |||
| } | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public abstract class Prop<T> { | |||
| private T value; | |||
| public Prop() { } | |||
| public Prop(T defaultValue) { | |||
| value = defaultValue; | |||
| } | |||
| abstract T toValue(Dynamic value); | |||
| public void setValue(Dynamic value){ | |||
| this.value = toValue(value); | |||
| } | |||
| public void setValue(T value){ | |||
| this.value = value; | |||
| } | |||
| public T getValue(){ | |||
| return value; | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public class TextColorProp extends Prop<String> { | |||
| public static final String name = "textColor"; | |||
| @Override | |||
| public String toValue(Dynamic value){ | |||
| return value.asString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,12 @@ | |||
| package com.henninghall.date_picker.props; | |||
| import com.facebook.react.bridge.Dynamic; | |||
| public class UtcProp extends Prop<Boolean> { | |||
| public static final String name = "utc"; | |||
| @Override | |||
| Boolean toValue(Dynamic value) { | |||
| return value.asBoolean(); | |||
| } | |||
| } | |||
| @ -0,0 +1,45 @@ | |||
| package com.henninghall.date_picker.ui; | |||
| import android.view.View; | |||
| import com.henninghall.date_picker.PickerView; | |||
| import com.henninghall.date_picker.State; | |||
| import com.henninghall.date_picker.Utils; | |||
| import java.util.HashMap; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| public class EmptyWheels { | |||
| private final HashMap<Integer, NumberPickerView> views; | |||
| private final Wheels wheels; | |||
| private View rootView; | |||
| private State state; | |||
| EmptyWheels(View rootView, Wheels wheels, State state) { | |||
| this.wheels = wheels; | |||
| this.rootView = rootView; | |||
| this.state = state; | |||
| this.views = getViews(); | |||
| } | |||
| private HashMap<Integer, NumberPickerView> getViews() { | |||
| HashMap<Integer, NumberPickerView> views = new HashMap<>(); | |||
| for (int id: Utils.emptyWheelIds) { | |||
| NumberPickerView view = (NumberPickerView) rootView.findViewById(id); | |||
| views.put(id, view); | |||
| } | |||
| return views; | |||
| } | |||
| void add() { | |||
| int numberOfVisibleWheels = state.getVisibleWheels().size(); | |||
| int emptyViewsToAdd = numberOfVisibleWheels + 1; | |||
| for (int i = 0; i < emptyViewsToAdd; i++) { | |||
| int index = i * 2; | |||
| wheels.addWheel(views.get(Utils.emptyWheelIds[i]), index); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,42 @@ | |||
| package com.henninghall.date_picker.ui; | |||
| import android.graphics.Color; | |||
| import android.graphics.drawable.GradientDrawable; | |||
| import android.view.View; | |||
| import android.widget.ImageView; | |||
| import com.henninghall.date_picker.R; | |||
| import com.henninghall.date_picker.State; | |||
| public class FadingOverlay { | |||
| private final GradientDrawable gradientTop; | |||
| private final GradientDrawable gradientBottom; | |||
| private final State state; | |||
| public FadingOverlay(State state, View rootView) { | |||
| this.state = state; | |||
| ImageView overlayTop = (ImageView) rootView.findViewById(R.id.overlay_top); | |||
| ImageView overlayBottom = (ImageView) rootView.findViewById(R.id.overlay_bottom); | |||
| gradientTop = (GradientDrawable) overlayTop.getDrawable(); | |||
| gradientBottom = (GradientDrawable) overlayBottom.getDrawable(); | |||
| } | |||
| public void updateColor(){ | |||
| String color = state.getFadeToColor(); | |||
| int alpha = validColor(color) ? 255 : 0; | |||
| gradientTop.setAlpha(alpha); | |||
| gradientBottom.setAlpha(alpha); | |||
| if(validColor(color)) { | |||
| int startColor = Color.parseColor("#FF"+ color.substring(1)); | |||
| int endColor = Color.parseColor("#00" + color.substring(1)); | |||
| gradientTop.setColors(new int[] {startColor, endColor}); | |||
| gradientBottom.setColors(new int[] {startColor, endColor}); | |||
| } | |||
| } | |||
| private boolean validColor(String color){ | |||
| return color != null && color.length() == 7; | |||
| } | |||
| } | |||
| @ -0,0 +1,87 @@ | |||
| package com.henninghall.date_picker.ui; | |||
| import android.view.View; | |||
| import com.henninghall.date_picker.State; | |||
| import com.henninghall.date_picker.Utils; | |||
| import com.henninghall.date_picker.wheelFunctions.AnimateToDate; | |||
| import com.henninghall.date_picker.wheelFunctions.Refresh; | |||
| import com.henninghall.date_picker.wheelFunctions.SetDate; | |||
| import com.henninghall.date_picker.wheelFunctions.SetShowCount; | |||
| import com.henninghall.date_picker.wheelFunctions.TextColor; | |||
| import com.henninghall.date_picker.wheelFunctions.UpdateVisibility; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| public class UIManager { | |||
| private final State state; | |||
| private final View rootView; | |||
| private Wheels wheels; | |||
| private FadingOverlay fadingOverlay; | |||
| private WheelScroller wheelScroller = new WheelScroller(); | |||
| public UIManager(State state, View rootView){ | |||
| this.rootView = rootView; | |||
| this.state = state; | |||
| wheels = new Wheels(state, rootView, this); | |||
| fadingOverlay = new FadingOverlay(state, rootView); | |||
| } | |||
| public void updateWheelVisibility(){ | |||
| wheels.applyOnAll(new UpdateVisibility()); | |||
| } | |||
| public void updateTextColor(){ | |||
| wheels.applyOnAll(new TextColor(state.getTextColor())); | |||
| } | |||
| public void updateFadeToColor(){ | |||
| fadingOverlay.updateColor(); | |||
| } | |||
| public void updateHeight(){ | |||
| int shownCount = state.getShownCount(); | |||
| wheels.applyOnAll(new SetShowCount(shownCount)); | |||
| setShownCountOnEmptyWheels(shownCount); | |||
| } | |||
| public void updateWheelOrder() { | |||
| wheels.removeAll(); | |||
| wheels.addInOrder(); | |||
| wheels.addEmpty(); | |||
| } | |||
| public void updateDisplayValues(){ | |||
| wheels.applyOnAll(new Refresh()); | |||
| } | |||
| public void setWheelsToDate(){ | |||
| wheels.applyOnAll(new SetDate(state.getDate())); | |||
| } | |||
| public void scroll(int wheelIndex, int scrollTimes) { | |||
| Wheel wheel = wheels.getWheel(state.getOrderedVisibleWheels().get(wheelIndex)); | |||
| wheelScroller.scroll(wheel,scrollTimes); | |||
| } | |||
| SimpleDateFormat getDateFormat() { | |||
| return new SimpleDateFormat(wheels.getFormatPattern(), state.getLocale()); | |||
| } | |||
| void animateToDate(Calendar date) { | |||
| wheels.applyOnVisible(new AnimateToDate(date)); | |||
| } | |||
| private void setShownCountOnEmptyWheels(int shownCount) { | |||
| for (int id : Utils.emptyWheelIds) { | |||
| NumberPickerView view = (NumberPickerView) rootView.findViewById(id); | |||
| if(view != null) view.setShownCount(shownCount); | |||
| } | |||
| } | |||
| } | |||
| @ -1,4 +1,4 @@ | |||
| package com.henninghall.date_picker; | |||
| package com.henninghall.date_picker.ui; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| @ -0,0 +1,60 @@ | |||
| package com.henninghall.date_picker.ui; | |||
| import android.view.View; | |||
| import com.facebook.react.bridge.Arguments; | |||
| import com.facebook.react.bridge.WritableMap; | |||
| import com.facebook.react.uimanager.events.RCTEventEmitter; | |||
| import com.henninghall.date_picker.DatePickerManager; | |||
| import com.henninghall.date_picker.PickerView; | |||
| import com.henninghall.date_picker.State; | |||
| import com.henninghall.date_picker.Utils; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import java.text.ParseException; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| import java.util.Date; | |||
| import java.util.TimeZone; | |||
| public class WheelChangeListenerImpl implements WheelChangeListener { | |||
| private final Wheels wheels; | |||
| private final State state; | |||
| private final UIManager uiManager; | |||
| private final View rootView; | |||
| public WheelChangeListenerImpl(Wheels wheels, State state, UIManager uiManager, View rootView) { | |||
| this.wheels = wheels; | |||
| this.uiManager = uiManager; | |||
| this.state = state; | |||
| this.rootView = rootView; | |||
| } | |||
| @Override | |||
| public void onChange(Wheel picker) { | |||
| WritableMap event = Arguments.createMap(); | |||
| TimeZone timeZone = state.getTimeZone(); | |||
| SimpleDateFormat dateFormat = uiManager.getDateFormat(); | |||
| Calendar minDate = state.getMinimumDate(); | |||
| Calendar maxDate = state.getMaximumDate(); | |||
| try { | |||
| dateFormat.setTimeZone(timeZone); | |||
| Calendar date = Calendar.getInstance(timeZone); | |||
| String toParse = wheels.getDateString(); | |||
| Date newDate = dateFormat.parse(toParse); | |||
| date.setTime(newDate); | |||
| if (minDate != null && date.before(minDate)) uiManager.animateToDate(minDate); | |||
| else if (maxDate != null && date.after(maxDate)) uiManager.animateToDate(maxDate); | |||
| else { | |||
| event.putString("date", Utils.dateToIso(date)); | |||
| DatePickerManager.context.getJSModule(RCTEventEmitter.class) | |||
| .receiveEvent(rootView.getId(), "dateChange", event); | |||
| } | |||
| } catch (ParseException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,19 @@ | |||
| package com.henninghall.date_picker.ui; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| public class WheelScroller { | |||
| public void scroll(Wheel wheel, int scrollTimes) { | |||
| NumberPickerView picker = wheel.picker; | |||
| int currentIndex = picker.getValue(); | |||
| int maxValue = picker.getMaxValue(); | |||
| boolean isWrapping = picker.getWrapSelectorWheel(); | |||
| int nextValue = currentIndex + scrollTimes; | |||
| if(nextValue <= maxValue || isWrapping) { | |||
| picker.smoothScrollToValue(nextValue % (maxValue + 1)); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,186 @@ | |||
| package com.henninghall.date_picker.ui; | |||
| import android.view.View; | |||
| import android.widget.LinearLayout; | |||
| import com.henninghall.date_picker.R; | |||
| import com.henninghall.date_picker.State; | |||
| import com.henninghall.date_picker.Utils; | |||
| import com.henninghall.date_picker.models.WheelType; | |||
| import com.henninghall.date_picker.models.Mode; | |||
| import com.henninghall.date_picker.wheelFunctions.AddOnChangeListener; | |||
| import com.henninghall.date_picker.wheelFunctions.WheelFunction; | |||
| import com.henninghall.date_picker.wheels.AmPmWheel; | |||
| import com.henninghall.date_picker.wheels.DateWheel; | |||
| import com.henninghall.date_picker.wheels.DayWheel; | |||
| import com.henninghall.date_picker.wheels.HourWheel; | |||
| import com.henninghall.date_picker.wheels.MinutesWheel; | |||
| import com.henninghall.date_picker.wheels.MonthWheel; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import com.henninghall.date_picker.wheels.YearWheel; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.Collection; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| public class Wheels { | |||
| private final State state; | |||
| private HourWheel hourWheel; | |||
| private DayWheel dayWheel; | |||
| private MinutesWheel minutesWheel; | |||
| private AmPmWheel ampmWheel; | |||
| private DateWheel dateWheel; | |||
| private MonthWheel monthWheel; | |||
| private YearWheel yearWheel; | |||
| private View rootView; | |||
| private final LinearLayout wheelsWrapper; | |||
| private final EmptyWheels emptyWheels; | |||
| private HashMap<WheelType, Wheel> wheelPerWheelType; | |||
| private UIManager uiManager; | |||
| Wheels(State state, View rootView, UIManager uiManager){ | |||
| this.state = state; | |||
| this.rootView = rootView; | |||
| this.uiManager = uiManager; | |||
| wheelsWrapper = (LinearLayout) rootView.findViewById(R.id.wheelsWrapper); | |||
| wheelsWrapper.setWillNotDraw(false); | |||
| yearWheel = new YearWheel(getPickerWithId(R.id.year), state); | |||
| monthWheel = new MonthWheel(getPickerWithId(R.id.month), state); | |||
| dateWheel = new DateWheel(getPickerWithId(R.id.date), state); | |||
| dayWheel = new DayWheel(getPickerWithId(R.id.day), state); | |||
| minutesWheel = new MinutesWheel(getPickerWithId(R.id.minutes), state); | |||
| ampmWheel = new AmPmWheel(getPickerWithId(R.id.ampm), state); | |||
| hourWheel = new HourWheel(getPickerWithId(R.id.hour), state); | |||
| wheelPerWheelType = getWheelPerType(); | |||
| changeAmPmWhenPassingMidnightOrNoon(); | |||
| addOnChangeListener(); | |||
| emptyWheels = new EmptyWheels(rootView,this,state); | |||
| } | |||
| private void addOnChangeListener(){ | |||
| WheelChangeListener onWheelChangeListener = new WheelChangeListenerImpl(this, state, uiManager, rootView); | |||
| applyOnAll(new AddOnChangeListener(onWheelChangeListener)); | |||
| } | |||
| private NumberPickerView getPickerWithId(int id){ | |||
| return (NumberPickerView) rootView.findViewById(id); | |||
| } | |||
| private Collection<Wheel> getVisible() { | |||
| ArrayList<WheelType> wheelTypes = state.getVisibleWheels(); | |||
| Collection<Wheel> wheels = new ArrayList<>(); | |||
| for (WheelType type: wheelTypes){ | |||
| wheels.add(getWheel(type)); | |||
| } | |||
| return wheels; | |||
| } | |||
| void applyOnAll(WheelFunction function) { | |||
| for (Wheel wheel: getAll()) function.apply(wheel); | |||
| } | |||
| void applyOnVisible(WheelFunction function) { | |||
| for (Wheel wheel: getVisible()) function.apply(wheel); | |||
| } | |||
| Wheel getWheel(WheelType type){ | |||
| return wheelPerWheelType.get(type); | |||
| } | |||
| void addInOrder(){ | |||
| ArrayList<WheelType> wheels = state.getOrderedVisibleWheels(); | |||
| for (WheelType wheelType : wheels) { | |||
| Wheel wheel = getWheel(wheelType); | |||
| addWheel(wheel.picker); | |||
| } | |||
| } | |||
| private ArrayList<Wheel> getOrderedWheels(){ | |||
| ArrayList<Wheel> list = new ArrayList<>(); | |||
| for (WheelType type : state.getOrderedVisibleWheels()) { | |||
| list.add(getWheel(type)); | |||
| } | |||
| return list; | |||
| } | |||
| void addWheel(View wheel) { wheelsWrapper.addView(wheel); } | |||
| void addWheel(View wheel, int index) { wheelsWrapper.addView(wheel,index); } | |||
| void removeAll() { | |||
| wheelsWrapper.removeAllViews(); | |||
| } | |||
| private void changeAmPmWhenPassingMidnightOrNoon() { | |||
| hourWheel.picker.setOnValueChangeListenerInScrolling(new NumberPickerView.OnValueChangeListenerInScrolling() { | |||
| @Override | |||
| public void onValueChangeInScrolling(NumberPickerView picker, int oldVal, int newVal) { | |||
| if(Utils.usesAmPm()){ | |||
| String oldValue = hourWheel.getValueAtIndex(oldVal); | |||
| String newValue = hourWheel.getValueAtIndex(newVal); | |||
| boolean passingNoonOrMidnight = (oldValue.equals("12") && newValue.equals("11")) || oldValue.equals("11") && newValue.equals("12"); | |||
| if (passingNoonOrMidnight) ampmWheel.picker.smoothScrollToValue((ampmWheel.picker.getValue() + 1) % 2,false); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| private List<Wheel> getAll(){ | |||
| return new ArrayList<>(Arrays.asList(yearWheel, monthWheel, dateWheel, dayWheel, hourWheel, minutesWheel, ampmWheel)); | |||
| } | |||
| private String getDateFormatPattern(){ | |||
| ArrayList<Wheel> wheels = getOrderedWheels(); | |||
| if(state.getMode() == Mode.date){ | |||
| return wheels.get(0).getFormatPattern() + " " | |||
| + wheels.get(1).getFormatPattern() + " " | |||
| + wheels.get(2).getFormatPattern(); | |||
| } | |||
| return dayWheel.getFormatPattern(); | |||
| } | |||
| public String getFormatPattern() { | |||
| return this.getDateFormatPattern() + " " | |||
| + hourWheel.getFormatPattern() + " " | |||
| + minutesWheel.getFormatPattern() | |||
| + ampmWheel.getFormatPattern(); | |||
| } | |||
| String getDateString() { | |||
| ArrayList<Wheel> wheels = getOrderedWheels(); | |||
| String dateString = (state.getMode() == Mode.date) | |||
| ? wheels.get(0).getValue() + " " | |||
| + wheels.get(1).getValue() + " " | |||
| + wheels.get(2).getValue() | |||
| : dayWheel.getValue(); | |||
| return dateString | |||
| + " " + hourWheel.getValue() | |||
| + " " + minutesWheel.getValue() | |||
| + ampmWheel.getValue(); | |||
| } | |||
| private HashMap<WheelType, Wheel> getWheelPerType(){ | |||
| return new HashMap<WheelType, Wheel>() {{ | |||
| put(WheelType.DAY, dayWheel); | |||
| put(WheelType.YEAR, yearWheel); | |||
| put(WheelType.MONTH,monthWheel); | |||
| put(WheelType.DATE, dateWheel); | |||
| put(WheelType.HOUR, hourWheel); | |||
| put(WheelType.MINUTE, minutesWheel); | |||
| put(WheelType.AM_PM, ampmWheel); | |||
| }}; | |||
| } | |||
| void addEmpty() { | |||
| emptyWheels.add(); | |||
| } | |||
| } | |||
| @ -0,0 +1,27 @@ | |||
| package com.henninghall.date_picker.wheelFunctions; | |||
| import com.henninghall.date_picker.ui.WheelChangeListener; | |||
| import com.henninghall.date_picker.wheels.Wheel; | |||
| import cn.carbswang.android.numberpickerview.library.NumberPickerView; | |||
| public class AddOnChangeListener implements WheelFunction { | |||
| private final WheelChangeListener onChangeListener; | |||
| public AddOnChangeListener(WheelChangeListener onChangeListener){ | |||
| this.onChangeListener = onChangeListener; | |||
| } | |||
| @Override | |||
| public void apply(final Wheel wheel) { | |||
| wheel.picker.setOnValueChangedListener(new NumberPickerView.OnValueChangeListener() { | |||
| @Override | |||
| public void onValueChange(NumberPickerView picker, int oldVal, int newVal) { | |||
| onChangeListener.onChange(wheel); | |||
| } | |||
| }); | |||
| } | |||
| } | |||