blob: ae745a1c23e3add18f4df1b177f0e2a6f24e9db7 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.touch_to_fill.helper;
import android.database.DataSetObserver;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import org.chromium.ui.modelutil.ListObservable;
import java.util.HashSet;
import java.util.Set;
/**
* This Adapter creates Views of type {@link V} for a {@link android.widget.ListView} and binds
* items of type {@link T} to each of the created views. It defers most tasks to a {@link Delegate}.
*
* Construct with a {@link SimpleListViewMcp} to update a ListView according to a list model.
*
* @param <T> The item type inside the observed list. It's passed to the {@link Delegate}.
* @param <V> The view type of a single list entry as created by the {@link ViewFactory}.
*/
public class ListViewAdapter<T, V extends View>
implements ListObservable.ListObserver<Void>, ListAdapter {
private final Delegate<T, V> mDelegate;
private final ViewFactory<V> mViewFactory;
private final Set<DataSetObserver> mObservers = new HashSet<>();
/**
* This delegates decouples the ListViewAdapter from the underlying model and handles all tasks
* for which the model might be necessary.
* @param <T> The item type inside the observed list.
* @param <V> The view type of a single list entry as created by the {@link ViewFactory}.
*/
public interface Delegate<T, V extends View> {
/**
* Returns the list item at the given position.
* @param pos The position inside the list to retrieve the item for.
* @return An item of type {@link T}.
*/
T getItemAt(int pos);
/**
* @return The total number of items in the observed list.
*/
int getItemCount();
/**
* Binds the data of the given item to the given View.
* @param view A View inside the ListView of type {@link V}.
* @param item An Item inside the observed list of type {@link T}.
*/
void onBindView(V view, T item);
}
/**
* Subclasses of this interface create the View that represents an item in a ListView.
* @param <V> The type of {@link View} this factory creates.
*/
public interface ViewFactory<V extends View> {
/**
* Creates a View used in a ListView and attaches it to the given parent.
* @param parent The parent of the newly created View.
* @return A {@link View} that represents an item in a ListView.
*/
V create(ViewGroup parent);
}
/**
* Creates a new ListViewAdapter.
* @param delegate The {@link Delegate} to bind views and query for list information.
* @param viewFactory The {@link ViewFactory} used to create new views for the ListView.
*/
public ListViewAdapter(Delegate<T, V> delegate, ViewFactory<V> viewFactory) {
mDelegate = delegate;
mViewFactory = viewFactory;
}
@Override
public void onItemMoved(ListObservable source, int curIndex, int newIndex) {
notifyObserversChanged();
}
@Override
public void onItemRangeChanged(
ListObservable source, int index, int count, @Nullable Void payload) {
notifyObserversChanged();
}
@Override
public void onItemRangeInserted(ListObservable source, int index, int count) {
notifyObserversChanged();
}
@Override
public void onItemRangeRemoved(ListObservable source, int index, int count) {
notifyObserversChanged();
}
private void notifyObserversChanged() {
for (DataSetObserver observer : mObservers) observer.onChanged();
}
@Override
public void registerDataSetObserver(DataSetObserver dataSetObserver) {
mObservers.add(dataSetObserver);
}
@Override
public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {
mObservers.remove(dataSetObserver);
}
@Override
public int getCount() {
return mDelegate.getItemCount();
}
@Override
public Object getItem(int i) {
return mDelegate.getItemAt(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
@SuppressWarnings("unchecked")
public View getView(int pos, View view, ViewGroup parent) {
if (view == null) view = mViewFactory.create(parent);
mDelegate.onBindView((V) view, mDelegate.getItemAt(pos));
return view;
}
@Override
public int getItemViewType(int i) {
return 0; // Always the same view type.
}
@Override
public int getViewTypeCount() {
return 1; // Always the same view type.
}
@Override
public boolean isEmpty() {
return mDelegate.getItemCount() == 0;
}
@Override
public boolean areAllItemsEnabled() {
return true; // There are no disabled items yet.
}
@Override
public boolean isEnabled(int i) {
return true; // There are no disabled items yet.
}
}