Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>master
@@ -41,6 +41,7 @@ import com.wireguard.android.model.Tunnel; | |||
import com.wireguard.android.util.ExceptionLoggers; | |||
import com.wireguard.android.util.ObservableSortedKeyedList; | |||
import com.wireguard.android.widget.MonkeyedSnackbar; | |||
import com.wireguard.android.widget.MultiselectableRelativeLayout; | |||
import com.wireguard.android.widget.fab.FloatingActionsMenuRecyclerViewScrollListener; | |||
import com.wireguard.config.Config; | |||
@@ -263,30 +264,20 @@ public class TunnelListFragment extends BaseFragment { | |||
super.onPause(); | |||
} | |||
private MultiselectableRelativeLayout viewForTunnel(final Tunnel tunnel, final List tunnels) { | |||
return (MultiselectableRelativeLayout)binding.tunnelList.findViewHolderForAdapterPosition(tunnels.indexOf(tunnel)).itemView; | |||
} | |||
@Override | |||
public void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) { | |||
if (binding == null) | |||
return; | |||
Application.getTunnelManager().getTunnels().thenAccept(tunnels -> { | |||
if (newTunnel != null) | |||
binding.tunnelList.findViewHolderForAdapterPosition(tunnels.indexOf(newTunnel)).itemView.setActivated(true); | |||
viewForTunnel(newTunnel, tunnels).setSingleSelected(true); | |||
if (oldTunnel != null) | |||
binding.tunnelList.findViewHolderForAdapterPosition(tunnels.indexOf(oldTunnel)).itemView.setActivated(false); | |||
viewForTunnel(oldTunnel, tunnels).setSingleSelected(false); | |||
}); | |||
/* Alternative 1: results in sluggish change: | |||
if (binding.tunnelList.getAdapter() == null) | |||
return; | |||
* Alternative 2: results in overly quick change: | |||
binding.tunnelList.getAdapter().notifyDataSetChanged(); | |||
* Hence, we go with the above. | |||
*/ | |||
} | |||
private void onTunnelDeletionFinished(final Integer count, @Nullable final Throwable throwable) { | |||
@@ -373,10 +364,9 @@ public class TunnelListFragment extends BaseFragment { | |||
}); | |||
if (actionMode != null) | |||
binding.getRoot().setActivated(actionModeListener.checkedItems.contains(position)); | |||
((MultiselectableRelativeLayout)binding.getRoot()).setMultiSelected(actionModeListener.checkedItems.contains(position)); | |||
else | |||
binding.getRoot().setActivated(getSelectedTunnel() == tunnel); | |||
((MultiselectableRelativeLayout)binding.getRoot()).setSingleSelected(getSelectedTunnel() == tunnel); | |||
}); | |||
} | |||
@@ -433,7 +423,6 @@ public class TunnelListFragment extends BaseFragment { | |||
public void onDestroyActionMode(final ActionMode mode) { | |||
actionMode = null; | |||
resources = null; | |||
checkedItems.clear(); | |||
binding.tunnelList.getAdapter().notifyDataSetChanged(); | |||
} | |||
@@ -0,0 +1,57 @@ | |||
/* | |||
* Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. | |||
* SPDX-License-Identifier: Apache-2.0 | |||
*/ | |||
package com.wireguard.android.widget; | |||
import android.content.Context; | |||
import android.util.AttributeSet; | |||
import android.widget.RelativeLayout; | |||
import com.wireguard.android.R; | |||
public class MultiselectableRelativeLayout extends RelativeLayout { | |||
public MultiselectableRelativeLayout(final Context context) { | |||
super(context); | |||
} | |||
public MultiselectableRelativeLayout(final Context context, final AttributeSet attrs) { | |||
super(context, attrs); | |||
} | |||
public MultiselectableRelativeLayout(final Context context, final AttributeSet attrs, final int defStyleAttr) { | |||
super(context, attrs, defStyleAttr); | |||
} | |||
public MultiselectableRelativeLayout(final Context context, final AttributeSet attrs, final int defStyleAttr, final int defStyleRes) { | |||
super(context, attrs, defStyleAttr, defStyleRes); | |||
} | |||
private static final int[] STATE_MULTISELECTED = { R.attr.state_multiselected }; | |||
private boolean multiselected; | |||
@Override | |||
protected int[] onCreateDrawableState(final int extraSpace) { | |||
if (multiselected) { | |||
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); | |||
mergeDrawableStates(drawableState, STATE_MULTISELECTED); | |||
return drawableState; | |||
} | |||
return super.onCreateDrawableState(extraSpace); | |||
} | |||
public void setMultiSelected(final boolean on) { | |||
if (!multiselected) { | |||
multiselected = true; | |||
refreshDrawableState(); | |||
} | |||
setActivated(on); | |||
} | |||
public void setSingleSelected(final boolean on) { | |||
if (multiselected) { | |||
multiselected = false; | |||
refreshDrawableState(); | |||
} | |||
setActivated(on); | |||
} | |||
} |
@@ -1,12 +1,13 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto"> | |||
<item> | |||
<selector> | |||
<item android:state_activated="true"> | |||
<item app:state_multiselected="true" android:state_activated="true"> | |||
<color android:color="?android:attr/colorControlActivated" /> | |||
</item> | |||
<item app:state_multiselected="false" android:state_activated="true"> | |||
<color android:color="?android:attr/colorControlHighlight" /> | |||
<!-- TODO(msf): depending on whether or not we are in multiselect mode, choose instead: | |||
<color android:color="?android:attr/colorControlActivated" /> | |||
--> | |||
</item> | |||
</selector> | |||
</item> | |||
@@ -25,7 +25,7 @@ | |||
type="com.wireguard.android.fragment.TunnelListFragment" /> | |||
</data> | |||
<RelativeLayout | |||
<com.wireguard.android.widget.MultiselectableRelativeLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:background="@drawable/list_item_background" | |||
@@ -51,5 +51,5 @@ | |||
android:layout_alignParentEnd="true" | |||
app:checked="@{item.state == State.UP}" | |||
app:onBeforeCheckedChanged="@{fragment::setTunnelState}" /> | |||
</RelativeLayout> | |||
</com.wireguard.android.widget.MultiselectableRelativeLayout> | |||
</layout> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<resources> | |||
<declare-styleable name="Multiselected"> | |||
<attr name="state_multiselected" format="boolean"/> | |||
</declare-styleable> | |||
</resources> |