package com.circlegate.liban.adapter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.circlegate.liban.R;
import com.circlegate.liban.view.CustomListView;
import com.circlegate.liban.view.LoadingView;
import com.google.common.collect.ImmutableList;
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
public abstract class BaseAdapterInfiniteStartEnd<Item> extends BaseAdapter {
public static final int SCROLL_NONE = 0;
public static final int SCROLL_TO_START = 1;
public static final int SCROLL_TO_END = 2;
public static final int VIEW_TYPE_ITEM = 0;
public static final int VIEW_TYPE_LOAD_MORE = 1;
public static final int VIEW_TYPE_COUNT = 2;
private final CustomListView listView; // potrebujeme jenom kvuli setSelectionFromTop u pridavani polozek pred start
private final boolean hasStartMoreBtn;
private final boolean showNoMoreStartEndButtons; // pokud je false, a soucasne je hasMoreItemsStart resp. hasMoreItemsEnd, tak se proste na dane strane adapteru nezobrazuje zadna polozka navic
private final Context context;
private final LayoutInflater inflater;
private final String textLoadMoreItemsStart; // jenom pokud hasStartMoreBtn == true
private final String textLoadingMoreItemsStart; // jenom pokud hasStartMoreBtn == true
private final String textLoadingMoreItemsEnd;
private final String textNoMoreItemsStart; // jenom pokud je showNoMoreStartEndButtons == true
private final String textNoMoreItemsEnd; // jenom pokud je showNoMoreStartEndButtons == true
private final List<Item> items = new ArrayList<Item>();
private boolean hasMoreItemsStart;
private boolean isLoadingMoreItemsStart;
private boolean hasMoreItemsEnd;
private boolean wasLoadMoreItemsEndHandled;
private OnLoadMoreItemsListener onLoadMoreItemsListener;
public BaseAdapterInfiniteStartEnd(CustomListView listView,
String textLoadMoreItemsStart,
String textLoadingMoreItemsStart, String textLoadingMoreItemsEnd,
String textNoMoreItemsStart, String textNoMoreItemsEnd)
{
this(listView, true, true, textLoadMoreItemsStart, textLoadingMoreItemsStart, textLoadingMoreItemsEnd, textNoMoreItemsStart, textNoMoreItemsEnd);
}
/**
* Verze konstruktoru bez tlacitka pro nacteni predchozich
* @param listView
* @param textLoadingMoreItemsEnd
* @param textNoMoreItemsStart
* @param textNoMoreItemsEnd
*/
public BaseAdapterInfiniteStartEnd(CustomListView listView,
String textLoadingMoreItemsEnd,
String textNoMoreItemsStart, String textNoMoreItemsEnd)
{
this(listView, false, true, null, null, textLoadingMoreItemsEnd, textNoMoreItemsStart, textNoMoreItemsEnd);
}
public BaseAdapterInfiniteStartEnd(CustomListView listView,
boolean hasStartMoreBtn,
boolean showNoMoreStartEndButtons,
String textLoadMoreItemsStart,
String textLoadingMoreItemsStart, String textLoadingMoreItemsEnd,
String textNoMoreItemsStart, String textNoMoreItemsEnd)
{
this.listView = listView;
this.hasStartMoreBtn = hasStartMoreBtn;
this.showNoMoreStartEndButtons = showNoMoreStartEndButtons;
this.context = listView.getContext();
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.textLoadMoreItemsStart = textLoadMoreItemsStart;
this.textLoadingMoreItemsStart = textLoadingMoreItemsStart;
this.textLoadingMoreItemsEnd = textLoadingMoreItemsEnd;
this.textNoMoreItemsStart = textNoMoreItemsStart;
this.textNoMoreItemsEnd = textNoMoreItemsEnd;
}
//
// GETTERS
//
public Context getContext() {
return this.context;
}
public LayoutInflater getInflater() {
return this.inflater;
}
public boolean getHasMoreItemsStart() {
return hasMoreItemsStart;
}
public boolean getHasMoreItemsEnd() {
return hasMoreItemsEnd;
}
public int getItemsCount() {
return this.items.size();
}
public Item getItemAt(int index) {
return this.items.get(index);
}
public int getItemIndByPosition(int position) {
return position - getStartMoreBtnsCount();
}
public int getItemPositionByInd(int index) {
return index + getStartMoreBtnsCount();
}
public ImmutableList<Item> generateItems() {
return ImmutableList.copyOf(items);
}
public boolean isStartItem(int position) {
return position < getStartMoreBtnsCount();
}
public boolean isEndItem(int position) {
return position >= items.size() + getStartMoreBtnsCount();
}
public boolean isStartEndItem(int position) {
return isStartItem(position) || isEndItem(position);
}
public int getStartMoreBtnsCount() {
return (items.size() > 0 && hasStartMoreBtn && (hasMoreItemsStart || showNoMoreStartEndButtons)) ? 1 : 0;
}
public int getEndMoreBtnsCount() {
return (items.size() > 0 && (hasMoreItemsEnd || showNoMoreStartEndButtons)) ? 1 : 0;
}
//
// SETTERS
//
public void setItems(Collection<? extends Item> items, int scrollType) {
setItems(items, scrollType, true, true);
}
public void setItems(Collection<? extends Item> items, int scrollType, boolean hasMoreItemsStart, boolean hasMoreItemsEnd) {
if (items.size() == 0) {
clear();
}
else {
this.items.clear();
this.hasMoreItemsStart = hasMoreItemsStart;
this.isLoadingMoreItemsStart = false;
this.hasMoreItemsEnd = hasMoreItemsEnd;
this.wasLoadMoreItemsEndHandled = false;
this.items.addAll(0, items);
this.notifyDataSetChanged();
if (scrollType == SCROLL_TO_START) {
this.listView.setSelectionFromTop(listView.getHeaderViewsCount() + getStartMoreBtnsCount(), this.listView.getDividerHeight());
}
else if (scrollType == SCROLL_TO_END)
this.listView.setSelection(listView.getHeaderViewsCount() + items.size() - getStartMoreBtnsCount());
}
}
public void addItemsStart(final Collection<? extends Item> items) {
addItemsStart(items, false);
}
public void addItemsStart(final Collection<? extends Item> items, boolean removeFirstOldItem) {
int position;
final int headerViewsCount = listView.getHeaderViewsCount();
for (position = listView.getFirstVisiblePosition(); position < listView.getLastVisiblePosition(); position++) {
if (position > headerViewsCount + getStartMoreBtnsCount() + (removeFirstOldItem ? 1 : 0))
break;
}
final int offset = listView.getVisiblePositionOffset(position - listView.getFirstVisiblePosition());
this.hasMoreItemsStart = true;
this.isLoadingMoreItemsStart = false;
if (removeFirstOldItem)
this.items.remove(0);
this.items.addAll(0, items);
this.notifyDataSetChanged();
listView.setSelectionFromTop(position + items.size() + (removeFirstOldItem ? -1 : 0), offset - listView.getPaddingTop());// + listView.getPaddingTop() - listView.getDividerHeight());
if (hasStartMoreBtn || position != headerViewsCount + 1 || items.size() == 0) {
// nic
}
else if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
listView.smoothScrollToPositionFromTop(items.size() - 1 + headerViewsCount + getStartMoreBtnsCount(), listView.getPaddingTop() - listView.getDividerHeight(), 500);
}
else {
// Radsi nic...
//listView.scrollToPositionFromTop(items.size() - 1 + headerViewsCount + getStartMoreBtnsCount(), listView.getPaddingTop() - listView.getDividerHeight(), 500);
}
}
public void addItemsEnd(Collection<? extends Item> items) {
this.hasMoreItemsEnd = true;
this.wasLoadMoreItemsEndHandled = false;
this.items.addAll(items);
this.notifyDataSetChanged();
}
public void replaceItemDontNotify(int index, Item item) {
this.items.set(index, item);
}
public void replaceItemsDontNotify(List<? extends Item> items) {
if (this.items.size() != items.size())
throw new RuntimeException("Wrong items count!");
this.items.clear();
this.items.addAll(items);
}
public void clear() {
if (items.size() != 0 ||
hasMoreItemsStart ||
isLoadingMoreItemsStart ||
hasMoreItemsEnd ||
wasLoadMoreItemsEndHandled)
{
this.items.clear();
this.hasMoreItemsStart = false;
this.isLoadingMoreItemsStart = false;
this.hasMoreItemsEnd = false;
this.wasLoadMoreItemsEndHandled = false;
notifyDataSetChanged();
}
}
public void setNoMoreItemsStart(boolean notify) {
if (items.size() > 0 ) {
this.hasMoreItemsStart = false;
this.isLoadingMoreItemsStart = false;
if (notify)
notifyDataSetChanged();
}
}
public void setNoMoreItemsEnd(boolean notify) {
if (items.size() > 0 ) {
this.wasLoadMoreItemsEndHandled = true;
this.hasMoreItemsEnd = false;
if (notify)
notifyDataSetChanged();
}
}
public boolean loadMoreItemsStart() {
if (!isLoadingMoreItemsStart && onLoadMoreItemsStart()) {
this.isLoadingMoreItemsStart = true;
this.hasMoreItemsStart = true;
notifyDataSetChanged();
return true;
}
else
return false;
}
//
// OVERRIDES
//
@Override
public int getCount() {
return getStartMoreBtnsCount() + this.items.size() + getEndMoreBtnsCount();
}
@Override
public Item getItem(int position) {
return isStartEndItem(position) ? null : this.items.get(getItemIndByPosition(position));
}
@Override
public long getItemId(int position) {
if (isStartItem(position))
return Long.MIN_VALUE;
else if (isEndItem(position))
return Long.MAX_VALUE;
else
return getItemIdAtIndex(getItemIndByPosition(position));
}
@Override
public int getItemViewType(int position) {
return isStartEndItem(position) ? VIEW_TYPE_LOAD_MORE : VIEW_TYPE_ITEM;
}
@Override
public int getViewTypeCount() {
return VIEW_TYPE_COUNT;
}
@Override
public boolean isEnabled(int position) {
return !isStartEndItem(position) || (isStartItem(position) && hasMoreItemsStart);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (isStartEndItem(position)) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.adapter_loading_view, parent, false);
}
LoadingView v = (LoadingView)convertView;
if (position == 0) {
if (this.isLoadingMoreItemsStart) {
v.setProgresBarVisible(true);
v.setText(textLoadingMoreItemsStart);
}
else if (this.hasMoreItemsStart) {
v.setProgresBarVisible(false);
v.setText(textLoadMoreItemsStart);
}
else {
v.setProgresBarVisible(false);
v.setText(textNoMoreItemsStart);
}
setupLoadingView((LoadingView)convertView, true);
return convertView;
}
else {
if (!this.wasLoadMoreItemsEndHandled) {
this.wasLoadMoreItemsEndHandled = true;
this.hasMoreItemsEnd = onLoadMoreItemsEnd();
}
if (this.hasMoreItemsEnd) {
v.setProgresBarVisible(true);
v.setText(textLoadingMoreItemsEnd);
}
else {
v.setProgresBarVisible(false);
v.setText(textNoMoreItemsEnd);
}
setupLoadingView((LoadingView)convertView, false);
return convertView;
}
}
else {
return getViewItem(position, convertView, parent);
}
}
//
// PROTECTED
//
protected abstract View getViewItem(int position, View convertView, ViewGroup parent);
protected long getItemIdAtIndex(int index) {
return 0;
}
protected void setupLoadingView(LoadingView loadingView, boolean isStart) {
}
//
// LISTENERS
//
protected boolean onLoadMoreItemsStart() {
return this.onLoadMoreItemsListener != null && this.onLoadMoreItemsListener.onLoadMoreItemsStart();
}
protected boolean onLoadMoreItemsEnd() {
return this.onLoadMoreItemsListener != null && this.onLoadMoreItemsListener.onLoadMoreItemsEnd();
}
public void setOnLoadMoreItemsListener(OnLoadMoreItemsListener l) {
this.onLoadMoreItemsListener = l;
}
public interface OnLoadMoreItemsListener {
boolean onLoadMoreItemsStart();
boolean onLoadMoreItemsEnd();
}
}