package com.prolificinteractive.materialcalendarview; import android.support.annotation.NonNull; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; import com.prolificinteractive.materialcalendarview.MaterialCalendarView.ShowOtherDates; import com.prolificinteractive.materialcalendarview.format.DayFormatter; import com.prolificinteractive.materialcalendarview.format.TitleFormatter; import com.prolificinteractive.materialcalendarview.format.WeekDayFormatter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Pager adapter backing the calendar view */ abstract class CalendarPagerAdapter<V extends CalendarPagerView> extends PagerAdapter { private final ArrayDeque<V> currentViews; protected final MaterialCalendarView mcv; private final CalendarDay today; private TitleFormatter titleFormatter = null; private Integer color = null; private Integer dateTextAppearance = null; private Integer weekDayTextAppearance = null; @ShowOtherDates private int showOtherDates = MaterialCalendarView.SHOW_DEFAULTS; private CalendarDay minDate = null; private CalendarDay maxDate = null; private DateRangeIndex rangeIndex; private List<CalendarDay> selectedDates = new ArrayList<>(); private WeekDayFormatter weekDayFormatter = WeekDayFormatter.DEFAULT; private DayFormatter dayFormatter = DayFormatter.DEFAULT; private List<DayViewDecorator> decorators = new ArrayList<>(); private List<DecoratorResult> decoratorResults = null; private boolean selectionEnabled = true; CalendarPagerAdapter(MaterialCalendarView mcv) { this.mcv = mcv; this.today = CalendarDay.today(); currentViews = new ArrayDeque<>(); currentViews.iterator(); setRangeDates(null, null); } public void setDecorators(List<DayViewDecorator> decorators) { this.decorators = decorators; invalidateDecorators(); } public void invalidateDecorators() { decoratorResults = new ArrayList<>(); for (DayViewDecorator decorator : decorators) { DayViewFacade facade = new DayViewFacade(); decorator.decorate(facade); if (facade.isDecorated()) { decoratorResults.add(new DecoratorResult(decorator, facade)); } } for (V pagerView : currentViews) { pagerView.setDayViewDecorators(decoratorResults); } } @Override public int getCount() { return rangeIndex.getCount(); } @Override public CharSequence getPageTitle(int position) { return titleFormatter == null ? "" : titleFormatter.format(getItem(position)); } public CalendarPagerAdapter<?> migrateStateAndReturn(CalendarPagerAdapter<?> newAdapter) { newAdapter.titleFormatter = titleFormatter; newAdapter.color = color; newAdapter.dateTextAppearance = dateTextAppearance; newAdapter.weekDayTextAppearance = weekDayTextAppearance; newAdapter.showOtherDates = showOtherDates; newAdapter.minDate = minDate; newAdapter.maxDate = maxDate; newAdapter.selectedDates = selectedDates; newAdapter.weekDayFormatter = weekDayFormatter; newAdapter.dayFormatter = dayFormatter; newAdapter.decorators = decorators; newAdapter.decoratorResults = decoratorResults; newAdapter.selectionEnabled = selectionEnabled; return newAdapter; } public int getIndexForDay(CalendarDay day) { if (day == null) { return getCount() / 2; } if (minDate != null && day.isBefore(minDate)) { return 0; } if (maxDate != null && day.isAfter(maxDate)) { return getCount() - 1; } return rangeIndex.indexOf(day); } protected abstract V createView(int position); protected abstract int indexOf(V view); protected abstract boolean isInstanceOfView(Object object); protected abstract DateRangeIndex createRangeIndex(CalendarDay min, CalendarDay max); @Override public int getItemPosition(Object object) { if (!(isInstanceOfView(object))) { return POSITION_NONE; } CalendarPagerView pagerView = (CalendarPagerView) object; CalendarDay firstViewDay = pagerView.getFirstViewDay(); if (firstViewDay == null) { return POSITION_NONE; } int index = indexOf((V) object); if (index < 0) { return POSITION_NONE; } return index; } @Override public Object instantiateItem(ViewGroup container, int position) { V pagerView = createView(position); pagerView.setContentDescription(mcv.getCalendarContentDescription()); pagerView.setAlpha(0); pagerView.setSelectionEnabled(selectionEnabled); pagerView.setWeekDayFormatter(weekDayFormatter); pagerView.setDayFormatter(dayFormatter); if (color != null) { pagerView.setSelectionColor(color); } if (dateTextAppearance != null) { pagerView.setDateTextAppearance(dateTextAppearance); } if (weekDayTextAppearance != null) { pagerView.setWeekDayTextAppearance(weekDayTextAppearance); } pagerView.setShowOtherDates(showOtherDates); pagerView.setMinimumDate(minDate); pagerView.setMaximumDate(maxDate); pagerView.setSelectedDates(selectedDates); container.addView(pagerView); currentViews.add(pagerView); pagerView.setDayViewDecorators(decoratorResults); return pagerView; } public void setSelectionEnabled(boolean enabled) { selectionEnabled = enabled; for (V pagerView : currentViews) { pagerView.setSelectionEnabled(selectionEnabled); } } @Override public void destroyItem(ViewGroup container, int position, Object object) { CalendarPagerView pagerView = (CalendarPagerView) object; currentViews.remove(pagerView); container.removeView(pagerView); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } public void setTitleFormatter(@NonNull TitleFormatter titleFormatter) { this.titleFormatter = titleFormatter; } public void setSelectionColor(int color) { this.color = color; for (V pagerView : currentViews) { pagerView.setSelectionColor(color); } } public void setDateTextAppearance(int taId) { if (taId == 0) { return; } this.dateTextAppearance = taId; for (V pagerView : currentViews) { pagerView.setDateTextAppearance(taId); } } public void setShowOtherDates(@ShowOtherDates int showFlags) { this.showOtherDates = showFlags; for (V pagerView : currentViews) { pagerView.setShowOtherDates(showFlags); } } public void setWeekDayFormatter(WeekDayFormatter formatter) { this.weekDayFormatter = formatter; for (V pagerView : currentViews) { pagerView.setWeekDayFormatter(formatter); } } public void setDayFormatter(DayFormatter formatter) { this.dayFormatter = formatter; for (V pagerView : currentViews) { pagerView.setDayFormatter(formatter); } } @ShowOtherDates public int getShowOtherDates() { return showOtherDates; } public void setWeekDayTextAppearance(int taId) { if (taId == 0) { return; } this.weekDayTextAppearance = taId; for (V pagerView : currentViews) { pagerView.setWeekDayTextAppearance(taId); } } public void setRangeDates(CalendarDay min, CalendarDay max) { this.minDate = min; this.maxDate = max; for (V pagerView : currentViews) { pagerView.setMinimumDate(min); pagerView.setMaximumDate(max); } if (min == null) { min = CalendarDay.from(today.getYear() - 200, today.getMonth(), today.getDay()); } if (max == null) { max = CalendarDay.from(today.getYear() + 200, today.getMonth(), today.getDay()); } rangeIndex = createRangeIndex(min, max); notifyDataSetChanged(); invalidateSelectedDates(); } public DateRangeIndex getRangeIndex() { return rangeIndex; } public void clearSelections() { selectedDates.clear(); invalidateSelectedDates(); } public void setDateSelected(CalendarDay day, boolean selected) { if (selected) { if (!selectedDates.contains(day)) { selectedDates.add(day); invalidateSelectedDates(); } } else { if (selectedDates.contains(day)) { selectedDates.remove(day); invalidateSelectedDates(); } } } private void invalidateSelectedDates() { validateSelectedDates(); for (V pagerView : currentViews) { pagerView.setSelectedDates(selectedDates); } } private void validateSelectedDates() { for (int i = 0; i < selectedDates.size(); i++) { CalendarDay date = selectedDates.get(i); if ((minDate != null && minDate.isAfter(date)) || (maxDate != null && maxDate.isBefore(date))) { selectedDates.remove(i); mcv.onDateUnselected(date); i -= 1; } } } public CalendarDay getItem(int position) { return rangeIndex.getItem(position); } @NonNull public List<CalendarDay> getSelectedDates() { return Collections.unmodifiableList(selectedDates); } protected int getDateTextAppearance() { return dateTextAppearance == null ? 0 : dateTextAppearance; } protected int getWeekDayTextAppearance() { return weekDayTextAppearance == null ? 0 : weekDayTextAppearance; } }