diff options
author | Eric Kuck <eric@bluelinelabs.com> | 2018-07-04 16:47:55 -0500 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-07-06 04:14:19 +0200 |
commit | 500a705531a3210aa98b17b77085cf1ea86c274d (patch) | |
tree | 8eee63dc202e5e1414354f5827873a1e9c642be9 /app/src/main/java/com/wireguard/android/databinding | |
parent | 5729947d6ca3aa99d3811ca0e6624ad0ce0f969d (diff) |
AppListDialogFragment: add implementation for excluding applications
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
Diffstat (limited to 'app/src/main/java/com/wireguard/android/databinding')
-rw-r--r-- | app/src/main/java/com/wireguard/android/databinding/BindingAdapters.java | 34 | ||||
-rw-r--r-- | app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java | 135 |
2 files changed, 168 insertions, 1 deletions
diff --git a/app/src/main/java/com/wireguard/android/databinding/BindingAdapters.java b/app/src/main/java/com/wireguard/android/databinding/BindingAdapters.java index ba6845ba..9a4a9a27 100644 --- a/app/src/main/java/com/wireguard/android/databinding/BindingAdapters.java +++ b/app/src/main/java/com/wireguard/android/databinding/BindingAdapters.java @@ -9,16 +9,18 @@ package com.wireguard.android.databinding; import android.databinding.BindingAdapter; import android.databinding.ObservableList; import android.databinding.adapters.ListenerUtil; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.InputFilter; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.wireguard.android.R; -import com.wireguard.util.Keyed; import com.wireguard.android.util.ObservableKeyedList; import com.wireguard.android.widget.ToggleSwitch; import com.wireguard.android.widget.ToggleSwitch.OnBeforeCheckedChangeListener; +import com.wireguard.util.Keyed; /** * Static methods for use by generated code in the Android data binding library. @@ -91,9 +93,39 @@ public final class BindingAdapters { adapter.setList(newList); } + @BindingAdapter({"items", "layout"}) + public static <K, E extends Keyed<? extends K>> + void setItems(final RecyclerView view, + final ObservableKeyedList<K, E> oldList, final int oldLayoutId, + final ObservableKeyedList<K, E> newList, final int newLayoutId) { + if (view.getLayoutManager() == null) + view.setLayoutManager(new LinearLayoutManager(view.getContext(), RecyclerView.VERTICAL, false)); + + if (oldList == newList && oldLayoutId == newLayoutId) + return; + // The ListAdapter interface is not generic, so this cannot be checked. + @SuppressWarnings("unchecked") ObservableKeyedRecyclerViewAdapter<K, E> adapter = + (ObservableKeyedRecyclerViewAdapter<K, E>) view.getAdapter(); + // If the layout changes, any existing adapter must be replaced. + if (adapter != null && oldList != null && oldLayoutId != newLayoutId) { + adapter.setList(null); + adapter = null; + } + // Avoid setting an adapter when there is no new list or layout. + if (newList == null || newLayoutId == 0) + return; + if (adapter == null) { + adapter = new ObservableKeyedRecyclerViewAdapter<>(view.getContext(), newLayoutId, newList); + view.setAdapter(adapter); + } + // Either the list changed, or this is an entirely new listener because the layout changed. + adapter.setList(newList); + } + @BindingAdapter("onBeforeCheckedChanged") public static void setOnBeforeCheckedChanged(final ToggleSwitch view, final OnBeforeCheckedChangeListener listener) { view.setOnBeforeCheckedChangeListener(listener); } + } diff --git a/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java b/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java new file mode 100644 index 00000000..8917441f --- /dev/null +++ b/app/src/main/java/com/wireguard/android/databinding/ObservableKeyedRecyclerViewAdapter.java @@ -0,0 +1,135 @@ +package com.wireguard.android.databinding; + +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.databinding.ObservableList; +import android.databinding.ViewDataBinding; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.Adapter; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import com.wireguard.android.BR; +import com.wireguard.android.util.ObservableKeyedList; +import com.wireguard.util.Keyed; + +import java.lang.ref.WeakReference; + +/** + * A generic {@code RecyclerView.Adapter} backed by a {@code ObservableKeyedList}. + */ + +class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>> extends Adapter<ObservableKeyedRecyclerViewAdapter.ViewHolder> { + + private final OnListChangedCallback<E> callback = new OnListChangedCallback<>(this); + private final int layoutId; + private final LayoutInflater layoutInflater; + private ObservableKeyedList<K, E> list; + + ObservableKeyedRecyclerViewAdapter(final Context context, final int layoutId, + final ObservableKeyedList<K, E> list) { + this.layoutId = layoutId; + layoutInflater = LayoutInflater.from(context); + setList(list); + } + + @Override + public int getItemCount() { + return list != null ? list.size() : 0; + } + + private E getItem(final int position) { + if (list == null || position < 0 || position >= list.size()) + return null; + return list.get(position); + } + + @Override + public long getItemId(final int position) { + final K key = getKey(position); + return key != null ? key.hashCode() : -1; + } + + private K getKey(final int position) { + final E item = getItem(position); + return item != null ? item.getKey() : null; + } + + @NonNull @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new ViewHolder(DataBindingUtil.inflate(layoutInflater, layoutId, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + holder.binding.setVariable(BR.collection, list); + holder.binding.setVariable(BR.key, getKey(position)); + holder.binding.setVariable(BR.item, getItem(position)); + holder.binding.executePendingBindings(); + } + + void setList(final ObservableKeyedList<K, E> newList) { + if (list != null) + list.removeOnListChangedCallback(callback); + list = newList; + if (list != null) { + list.addOnListChangedCallback(callback); + } + notifyDataSetChanged(); + } + + private static final class OnListChangedCallback<E extends Keyed<?>> + extends ObservableList.OnListChangedCallback<ObservableList<E>> { + + private final WeakReference<ObservableKeyedRecyclerViewAdapter<?, E>> weakAdapter; + + private OnListChangedCallback(final ObservableKeyedRecyclerViewAdapter<?, E> adapter) { + weakAdapter = new WeakReference<>(adapter); + } + + @Override + public void onChanged(final ObservableList<E> sender) { + final ObservableKeyedRecyclerViewAdapter adapter = weakAdapter.get(); + if (adapter != null) + adapter.notifyDataSetChanged(); + else + sender.removeOnListChangedCallback(this); + } + + @Override + public void onItemRangeChanged(final ObservableList<E> sender, final int positionStart, + final int itemCount) { + onChanged(sender); + } + + @Override + public void onItemRangeInserted(final ObservableList<E> sender, final int positionStart, + final int itemCount) { + onChanged(sender); + } + + @Override + public void onItemRangeMoved(final ObservableList<E> sender, final int fromPosition, + final int toPosition, final int itemCount) { + onChanged(sender); + } + + @Override + public void onItemRangeRemoved(final ObservableList<E> sender, final int positionStart, + final int itemCount) { + onChanged(sender); + } + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + final ViewDataBinding binding; + + public ViewHolder(ViewDataBinding binding) { + super(binding.getRoot()); + + this.binding = binding; + } + } + +} |