package com.plusonelabs.calendar; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.support.annotation.NonNull; import android.util.Log; import android.widget.RemoteViews; import android.widget.RemoteViewsService.RemoteViewsFactory; import com.plusonelabs.calendar.calendar.CalendarEventVisualizer; import com.plusonelabs.calendar.prefs.InstanceSettings; import com.plusonelabs.calendar.widget.DayHeader; import com.plusonelabs.calendar.widget.WidgetEntry; import org.joda.time.DateTime; import java.util.ArrayList; import java.util.List; import java.util.Locale; import static com.plusonelabs.calendar.CalendarIntentUtil.*; import static com.plusonelabs.calendar.RemoteViewsUtil.*; import static com.plusonelabs.calendar.Theme.themeNameToResId; public class EventRemoteViewsFactory implements RemoteViewsFactory { private final Context context; private final int widgetId; private volatile List<WidgetEntry> mWidgetEntries = new ArrayList<>(); private final List<IEventVisualizer<?>> eventProviders; public EventRemoteViewsFactory(Context context, int widgetId) { this.context = context; this.widgetId = widgetId; eventProviders = new ArrayList<>(); eventProviders.add(new CalendarEventVisualizer(context, widgetId)); } public void onCreate() { RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget); rv.setPendingIntentTemplate(R.id.event_list, createOpenCalendarEventPendingIntent(getSettings())); } public void onDestroy() { // Empty } public int getCount() { return mWidgetEntries.size(); } public RemoteViews getViewAt(int position) { List<WidgetEntry> widgetEntries = mWidgetEntries; if (position < widgetEntries.size()) { WidgetEntry entry = widgetEntries.get(position); if (entry instanceof DayHeader) { return getRemoteView((DayHeader) entry); } for (IEventVisualizer<?> eventProvider : eventProviders) { if (entry.getClass().isAssignableFrom(eventProvider.getSupportedEventEntryType())) { return eventProvider.getRemoteView(entry); } } } return null; } private RemoteViews getRemoteView(DayHeader dayHeader) { String alignment = getSettings().getDayHeaderAlignment(); RemoteViews rv = new RemoteViews(context.getPackageName(), Alignment.valueOf(alignment).getLayoutId()); String dateString = DateUtil.createDayHeaderTitle(getSettings(), dayHeader.getStartDate()) .toUpperCase(Locale.getDefault()); rv.setTextViewText(R.id.day_header_title, dateString); setTextSize(getSettings(), rv, R.id.day_header_title, R.dimen.day_header_title); setTextColorFromAttr(context, rv, R.id.day_header_title, R.attr.dayHeaderTitle); setBackgroundColor(rv, R.id.day_header, dayHeader.getStartDay().plusDays(1).isBefore(DateUtil.now(getSettings().getTimeZone())) ? getSettings().getPastEventsBackgroundColor() : Color.TRANSPARENT); setBackgroundColorFromAttr(context, rv, R.id.day_header_separator, R.attr.dayHeaderSeparator); setPadding(getSettings(), rv, R.id.day_header_title, 0, R.dimen.day_header_padding_top, R.dimen.day_header_padding_right, R.dimen.day_header_padding_bottom); Intent intent = createOpenCalendarAtDayIntent(dayHeader.getStartDate()); rv.setOnClickFillInIntent(R.id.day_header, intent); return rv; } @NonNull private InstanceSettings getSettings() { return InstanceSettings.fromId(context, widgetId); } public void onDataSetChanged() { context.setTheme(themeNameToResId(getSettings().getEntryTheme())); if (getSettings().getShowDayHeaders()) mWidgetEntries = addDayHeaders(getEventEntries()); else mWidgetEntries = getEventEntries(); } private List<WidgetEntry> getEventEntries() { List<WidgetEntry> entries = new ArrayList<>(); for (IEventVisualizer<?> eventProvider : eventProviders) { entries.addAll(eventProvider.getEventEntries()); } return entries; } private List<WidgetEntry> addDayHeaders(List<WidgetEntry> listIn) { List<WidgetEntry> listOut = new ArrayList<>(); if (!listIn.isEmpty()) { boolean showDaysWithoutEvents = getSettings().getShowDaysWithoutEvents(); DayHeader curDayBucket = new DayHeader(new DateTime(0, getSettings().getTimeZone())); for (WidgetEntry entry : listIn) { DateTime nextStartOfDay = entry.getStartDay(); if (!nextStartOfDay.isEqual(curDayBucket.getStartDay())) { if (showDaysWithoutEvents) { addEmptyDayHeadersBetweenTwoDays(listOut, curDayBucket.getStartDay(), nextStartOfDay); } curDayBucket = new DayHeader(nextStartOfDay); listOut.add(curDayBucket); } listOut.add(entry); } } return listOut; } public void logWidgetEntries(String tag) { for (int ind = 0; ind < getWidgetEntries().size(); ind++) { WidgetEntry widgetEntry = getWidgetEntries().get(ind); Log.v(tag, String.format("%02d ", ind) + widgetEntry.toString()); } } List<WidgetEntry> getWidgetEntries() { return mWidgetEntries; } private void addEmptyDayHeadersBetweenTwoDays(List<WidgetEntry> entries, DateTime fromDayExclusive, DateTime toDayExclusive) { DateTime emptyDay = fromDayExclusive.plusDays(1); DateTime today = DateUtil.now(getSettings().getTimeZone()).withTimeAtStartOfDay(); if (emptyDay.isBefore(today)) { emptyDay = today; } while (emptyDay.isBefore(toDayExclusive)) { entries.add(new DayHeader(emptyDay)); emptyDay = emptyDay.plusDays(1); } } public RemoteViews getLoadingView() { return null; } public int getViewTypeCount() { int result = 3; // we have 3 because of the "left", "right" and "center" day headers for (IEventVisualizer<?> eventProvider : eventProviders) { result += eventProvider.getViewTypeCount(); } return result; } public long getItemId(int position) { return position; } public boolean hasStableIds() { return true; } }