Browse Source

Allow modification of selection (select all or invert) from the CAB.

pull/11/head
Eric Kok 11 years ago
parent
commit
852c5dd7dc
  1. 1
      core/res/values-v16/styles.xml
  2. 2
      core/res/values/strings.xml
  3. 28
      core/src/org/transdroid/core/gui/DetailsFragment.java
  4. 27
      core/src/org/transdroid/core/gui/TorrentsFragment.java
  5. 110
      core/src/org/transdroid/core/gui/navigation/SelectionManagerMode.java
  6. 98
      core/src/org/transdroid/core/gui/navigation/SelectionModificationSpinner.java

1
core/res/values-v16/styles.xml

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
<style name="DefaultTextView" parent="android:Widget.Holo.Light.TextView">
<item name="android:textSize">@dimen/text_default</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="LabelTextView" parent="android:Widget.Holo.Light.TextView">

2
core/res/values/strings.xml

@ -59,6 +59,8 @@ @@ -59,6 +59,8 @@
<item quantity="one">%1$d files selected</item>
<item quantity="other">%1$d files selected</item>
</plurals>
<string name="navigation_selectall">Select all</string>
<string name="navigation_invertselection">Invert selection</string>
<string name="status_status">STATUS: %1$s</string>
<string name="status_waiting">Waiting to check&#8230;</string>

28
core/src/org/transdroid/core/gui/DetailsFragment.java

@ -15,6 +15,7 @@ import org.transdroid.core.R; @@ -15,6 +15,7 @@ import org.transdroid.core.R;
import org.transdroid.core.gui.lists.DetailsAdapter;
import org.transdroid.core.gui.lists.SimpleListItemAdapter;
import org.transdroid.core.gui.navigation.NavigationHelper;
import org.transdroid.core.gui.navigation.SelectionManagerMode;
import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.Priority;
import org.transdroid.daemon.Torrent;
@ -248,13 +249,23 @@ public class DetailsFragment extends SherlockFragment { @@ -248,13 +249,23 @@ public class DetailsFragment extends SherlockFragment {
private MultiChoiceModeListenerCompat onDetailsSelected = new MultiChoiceModeListenerCompat() {
SelectionManagerMode selectionManagerMode;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Show contextual action bar to start/stop/remove/etc. torrents in batch mode
mode.getMenuInflater().inflate(R.menu.fragment_details_file, menu);
selectionManagerMode = new SelectionManagerMode(detailsList, R.plurals.navigation_filesselected);
selectionManagerMode.setOnlyCheckClass(TorrentFile.class);
selectionManagerMode.onCreateActionMode(mode, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return selectionManagerMode.onPrepareActionMode(mode, menu);
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
@ -292,25 +303,12 @@ public class DetailsFragment extends SherlockFragment { @@ -292,25 +303,12 @@ public class DetailsFragment extends SherlockFragment {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Show the number of selected files in the CAB
// torrentsList.getCheckedItemPositions().size() ?
int checkedCount = 0;
for (int i = 0; i < detailsList.getCheckedItemPositions().size(); i++) {
if (detailsList.getCheckedItemPositions().valueAt(i)
&& detailsList.getAdapter().getItem(detailsList.getCheckedItemPositions().keyAt(i)) instanceof TorrentFile)
checkedCount++;
}
mode.setTitle(getResources().getQuantityString(R.plurals.navigation_filesselected, checkedCount,
checkedCount));
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
selectionManagerMode.onItemCheckedStateChanged(mode, position, id, checked);
}
@Override
public void onDestroyActionMode(ActionMode mode) {
selectionManagerMode.onDestroyActionMode(mode);
}
};

27
core/src/org/transdroid/core/gui/TorrentsFragment.java

@ -17,6 +17,7 @@ import org.transdroid.core.app.settings.ApplicationSettings; @@ -17,6 +17,7 @@ import org.transdroid.core.app.settings.ApplicationSettings;
import org.transdroid.core.gui.lists.TorrentsAdapter;
import org.transdroid.core.gui.lists.TorrentsAdapter_;
import org.transdroid.core.gui.navigation.NavigationFilter;
import org.transdroid.core.gui.navigation.SelectionManagerMode;
import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentsComparator;
@ -182,15 +183,23 @@ public class TorrentsFragment extends SherlockFragment { @@ -182,15 +183,23 @@ public class TorrentsFragment extends SherlockFragment {
}
private MultiChoiceModeListenerCompat onTorrentsSelected = new MultiChoiceModeListenerCompat() {
SelectionManagerMode selectionManagerMode;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Show contextual action bar to start/stop/remove/etc. torrents in batch mode
mode.getMenuInflater().inflate(R.menu.fragment_torrents_cab, menu);
selectionManagerMode = new SelectionManagerMode(torrentsList, R.plurals.navigation_torrentsselected);
selectionManagerMode.onCreateActionMode(mode, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return selectionManagerMode.onPrepareActionMode(mode, menu);
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Get checked torrents
@ -237,24 +246,12 @@ public class TorrentsFragment extends SherlockFragment { @@ -237,24 +246,12 @@ public class TorrentsFragment extends SherlockFragment {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Show the number of selected torrents in the CAB
// torrentsList.getCheckedItemPositions().size() ?
int checkedCount = 0;
for (int i = 0; i < torrentsList.getCheckedItemPositions().size(); i++) {
if (torrentsList.getCheckedItemPositions().valueAt(i))
checkedCount++;
}
mode.setTitle(getResources().getQuantityString(R.plurals.navigation_torrentsselected, checkedCount,
checkedCount));
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
selectionManagerMode.onItemCheckedStateChanged(mode, position, id, checked);
}
@Override
public void onDestroyActionMode(ActionMode mode) {
selectionManagerMode.onDestroyActionMode(mode);
}
};

110
core/src/org/transdroid/core/gui/navigation/SelectionManagerMode.java

@ -0,0 +1,110 @@ @@ -0,0 +1,110 @@
package org.transdroid.core.gui.navigation;
import org.transdroid.core.gui.navigation.SelectionModificationSpinner.OnModificationActionSelectedListener;
import android.util.SparseBooleanArray;
import android.view.ViewGroup;
import android.widget.ListView;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SherlockListView.MultiChoiceModeListenerCompat;
/**
* A helper to implement {@link ListView} selection modification behaviour with the {@link SelectionModificationSpinner}
* by implementing the specific actions and providing a title based on the number of currently selected items. It is
* important that the provided list was instantiated already.
* @author Eric Kok
*/
public class SelectionManagerMode implements MultiChoiceModeListenerCompat, OnModificationActionSelectedListener {
private ListView managedList;
private int titleTemplateResource;
private Class<?> onlyCheckClass = null;
/**
* Instantiates the helper by binding it to a specific {@link ListView} and providing the text resource to display
* as title in the spinner.
* @param managedList The list to manage the selection for and execute selection action to
* @param titleTemplateResource The string resource id to show as the spinners title; the number of selected items
* will be supplied as numeric formatting argument
*/
public SelectionManagerMode(ListView managedList, int titleTemplateResource) {
this.managedList = managedList;
this.titleTemplateResource = titleTemplateResource;
}
/**
* Set the class type of items that are allowed to be checked in the {@link ListView}. Defaults to null, which means
* every list view row can be checked.
* @param onlyCheckClass The {@link Class} instance to use to check list item types against
*/
public void setOnlyCheckClass(Class<?> onlyCheckClass) {
this.onlyCheckClass = onlyCheckClass;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Allow modification of selection through a spinner
SelectionModificationSpinner selectionSpinner = new SelectionModificationSpinner(managedList.getContext());
selectionSpinner.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT));
selectionSpinner.setOnModificationActionSelectedListener(this);
mode.setCustomView(selectionSpinner);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
int checkedCount = 0;
for (int i = 0; i < managedList.getCheckedItemPositions().size(); i++) {
if (managedList.getCheckedItemPositions().valueAt(i))
checkedCount++;
}
((SelectionModificationSpinner) mode.getCustomView()).updateTitle(managedList.getContext().getResources()
.getQuantityString(titleTemplateResource, checkedCount, checkedCount));
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
/**
* Implements the {@link SelectionModificationSpinner}'s invert selection command by flipping the checked status for
* each (enabled) items in the {@link ListView}.
*/
@Override
public void invertSelection() {
SparseBooleanArray checked = managedList.getCheckedItemPositions();
for (int i = 0; i < managedList.getAdapter().getCount(); i++) {
if (managedList.getAdapter().isEnabled(i)
&& (onlyCheckClass == null || onlyCheckClass.isInstance(managedList.getItemAtPosition(i))))
managedList.setItemChecked(i, !checked.get(i, false));
}
}
/**
* Implements the {@link SelectionModificationSpinner}'s select all command by checking each (enabled) item in the
* {@link ListView}.
*/
@Override
public void selectionAll() {
for (int i = 0; i < managedList.getAdapter().getCount(); i++) {
if (managedList.getAdapter().isEnabled(i)
&& (onlyCheckClass == null || onlyCheckClass.isInstance(managedList.getItemAtPosition(i))))
managedList.setItemChecked(i, true);
}
}
}

98
core/src/org/transdroid/core/gui/navigation/SelectionModificationSpinner.java

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
package org.transdroid.core.gui.navigation;
import org.transdroid.core.R;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
/**
* Spinner that holds actions that can be performed on list selections. The spinner itself has some title, which can for
* example be used to show the number of selected items.
* @author Eric Kok
*/
public class SelectionModificationSpinner extends Spinner {
private SelectionDropDownAdapter selectionAdapter;
private OnModificationActionSelectedListener onModificationActionSelected = null;
/**
* Instantiates a spinner that contains some fixed actions for a user to modify selections.
* @param context The interface context where the spinner will be shown in
*/
public SelectionModificationSpinner(Context context) {
super(context);
selectionAdapter = new SelectionDropDownAdapter(context);
setAdapter(selectionAdapter);
}
/**
* Updates the fixed title text shown in the spinner, regardless of spinner item action selection.
* @param title The new static string to show, such as the number of selected items
*/
public void updateTitle(String title) {
selectionAdapter.titleView.setText(title);
invalidate();
}
/**
* Sets the listener for action selection events.
* @param onModificationActionSelected The listener that handles performing of the actions as selected in this
* spinner by the user
*/
public void setOnModificationActionSelectedListener(OnModificationActionSelectedListener onModificationActionSelected) {
this.onModificationActionSelected = onModificationActionSelected;
}
@Override
public void setSelection(int position) {
if (position == 0) {
onModificationActionSelected.selectionAll();
} else if (position == 1) {
onModificationActionSelected.invertSelection();
}
super.setSelection(position);
}
/**
* Local adapter that holds the actions which can be performed and a title text view that always shows instead of a
* list item as in a normal spinner.
*/
private class SelectionDropDownAdapter extends ArrayAdapter<String> {
protected TextView titleView = null;
public SelectionDropDownAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1, new String[] {
context.getString(R.string.navigation_selectall),
context.getString(R.string.navigation_invertselection) });
titleView = new TextView(getContext());
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// This returns the singleton text view showing the title with the number of selected items
return titleView;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
// This returns the actions to show in the spinner list
return super.getView(position, convertView, parent);
}
}
/**
* Interface to implement if an interface want to respond to selection modification actions.
*/
public interface OnModificationActionSelectedListener {
public void invertSelection();
public void selectionAll();
}
}
Loading…
Cancel
Save