package io.github.droidkaigi.confsched.fragment; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.util.ArrayMap; import android.util.Pair; import android.view.View; import org.parceler.Parcels; import java.util.ArrayList; import java.util.List; import java.util.Map; import io.github.droidkaigi.confsched.databinding.ItemSessionBinding; import io.github.droidkaigi.confsched.model.Session; import io.github.droidkaigi.confsched.widget.BindingHolder; public class MyScheduleSessionsTabFragment extends SessionsTabFragment { @NonNull public static MyScheduleSessionsTabFragment newInstance(List<Session> sessions) { MyScheduleSessionsTabFragment fragment = new MyScheduleSessionsTabFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_SESSIONS, Parcels.wrap(sessions)); fragment.setArguments(args); return fragment; } @Override protected SessionsAdapter createAdapter() { return new MyScheduleAdapter(getContext()); } private class MyScheduleAdapter extends SessionsAdapter { private Map<Long, Pair<Integer, Integer>> rangeMap = new ArrayMap<>(); public MyScheduleAdapter(@NonNull Context context) { super(context); } @Override public void onBindViewHolder(BindingHolder<ItemSessionBinding> holder, int position) { super.onBindViewHolder(holder, position); ItemSessionBinding binding = holder.binding; if (isConflicted(position)) { binding.txtConflict.setVisibility(View.VISIBLE); } else { binding.txtConflict.setVisibility(View.GONE); } } private Pair<Integer, Integer> getRangeOfConflictCandidates(int position) { Session session = getItem(position); if (rangeMap.containsKey(session.stime.getTime())) { return rangeMap.get(session.stime.getTime()); } List<Session> candidates = new ArrayList<>(); candidates.add(session); int startOffset = 1; while (position - startOffset >= 0) { Session s = getItem(position - startOffset); if (s.stime.getTime() == session.stime.getTime()) { candidates.add(s); } else { break; } startOffset++; } for (int offset = 1, count = getItemCount(); position + offset < count; offset++) { Session s = getItem(position + offset); if (s.stime.getTime() == session.stime.getTime()) { candidates.add(s); } else { break; } } Pair<Integer, Integer> range = Pair.create(position - startOffset + 1, candidates.size()); rangeMap.put(session.stime.getTime(), range); return range; } private boolean isConflicted(int position) { Session session = getItem(position); if (!session.checked) { return false; } Pair<Integer, Integer> range = getRangeOfConflictCandidates(position); for (int i = range.first; i < range.first + range.second; i++) { if (i == position) { continue; } if (getItem(i).checked) { return true; } } return false; } @Override protected void refresh(@NonNull Session session) { for (int i = 0, count = getItemCount(); i < count; i++) { Session s = getItem(i); if (session.equals(s)) { s.checked = session.checked; notifyItemChangedToAffected(i); break; } } } private void notifyItemChangedToAffected(int position) { Pair<Integer, Integer> range = getRangeOfConflictCandidates(position); notifyItemRangeChanged(range.first, range.second); } @Override protected void onLikeChanged(@NonNull Session session, int position) { super.onLikeChanged(session, position); Pair<Integer, Integer> range = getRangeOfConflictCandidates(position); if (range.second > 1) { notifyItemRangeChanged(range.first, range.second); } } } }