/* * Artcodes recognises a different marker scheme that allows the * creation of aesthetically pleasing, even beautiful, codes. * Copyright (C) 2013-2016 The University of Nottingham * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.horizon.artcodes.adapter; import android.content.Context; import android.support.v7.util.SortedList; import android.support.v7.widget.util.SortedListAdapterCallback; import com.google.common.collect.Ordering; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import uk.ac.horizon.artcodes.R; import uk.ac.horizon.artcodes.model.Experience; import uk.ac.horizon.artcodes.server.ArtcodeServer; import uk.ac.horizon.artcodes.server.LoadCallback; public class ExperienceSortedListAdapter extends ExperienceAdapter { private static final Ordering<String> STRING_ORDERING = Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsLast(); private final SortedList<Experience> experiences; public ExperienceSortedListAdapter(Context context, ArtcodeServer server) { super(context, server); experiences = new SortedList<>(Experience.class, new SortedListAdapterCallback<Experience>(adapter) { @Override public boolean areContentsTheSame(Experience oldItem, Experience newItem) { return oldItem.equals(newItem); } @Override public boolean areItemsTheSame(Experience item1, Experience item2) { return item1.equals(item2); } @Override public int compare(Experience o1, Experience o2) { int result = STRING_ORDERING.compare(o1.getName(), o2.getName()); if (result != 0) { return result; } return STRING_ORDERING.compare(o1.getId(), o2.getId()); } }); } @Override public Experience getExperience(final int position) { return experiences.get(position); } @Override public int getViewCount() { return experiences.size(); } @Override public void loaded(final List<String> items) { // If this adapter is empty, wait for all experiences to load before adding to adapter. // This is because if the experiences are added in non-alphabetical order the user can // be left in the middle of the list rather than the start. final boolean batchUpdate = experiences.size() == 0; final List<Experience> experiencesToBatchUpdate = new ArrayList<>(); final int[] count = {0}; synchronized (experiences) { for (int i = 0; i < experiences.size(); ++i) { Experience e = experiences.get(i); if (!items.contains(e.getId())) { experiences.remove(e); --i; } } } for (String uri : items) { loadStarted(); server.loadExperience(uri, new LoadCallback<Experience>() { @Override public void loaded(Experience experience) { loadFinished(); synchronized (experiences) { if (batchUpdate) { experiencesToBatchUpdate.add(experience); if (++count[0] == items.size()) { Collections.sort(experiencesToBatchUpdate, new Comparator<Experience>() { @Override public int compare(Experience experience1, Experience experience2) { return (experience1.getName()==null ? "" : experience1.getName()).compareTo(experience2.getName()==null ? "" : experience2.getName()); } }); for (Experience experienceFromBatchUpdate : experiencesToBatchUpdate) { experiences.add(experienceFromBatchUpdate); } experiencesToBatchUpdate.clear(); count[0] = 0; } } else { int index = -1; for (int i = 0; i < experiences.size(); ++i) { if (experience.equals(experiences.get(i))) { index = i; break; } } // experiences.indexOf(item) seems to be buggy. if (index > -1) { // experiences.updateItemAt() is ignored if a.equals(b) experiences.removeItemAt(index); experiences.add(experience); } else { experiences.add(experience); } } } } @Override public void error(Throwable e) { loadFinished(); showError(context.getString(R.string.connection_error)); if (batchUpdate && ++count[0] == items.size()) { for (Experience experienceFromBatchUpdate : experiencesToBatchUpdate) { experiences.add(experienceFromBatchUpdate); } } } }); } loadFinished(); } }