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 { | public enum Mode { | ||||
| date, time, datetime | date, time, datetime | ||||
| @ -1,4 +1,4 @@ | |||||
| package com.henninghall.date_picker; | |||||
| package com.henninghall.date_picker.models; | |||||
| public enum WheelType { | public enum WheelType { | ||||
| DAY, DATE, MONTH, YEAR, HOUR, MINUTE, AM_PM | 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; | 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); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||