From 2a061c0cc1f26ce018fcfb38080a8a38c16709f0 Mon Sep 17 00:00:00 2001 From: Joshua Bahnsen Date: Sat, 21 Dec 2013 09:58:21 -0700 Subject: [PATCH] Add drag and drop support to the playlist window --- .gitmodules | 3 ++ .idea/encodings.xml | 2 - .idea/modules.xml | 1 + Subsonic-Android.iml | 1 + drag-sort-listview | 1 + drag-sort-listview.iml | 34 ++++++++++++ menudrawer.iml | 14 ++--- project.properties | 3 +- .../ic_action_import_export_dark.png | Bin 0 -> 758 bytes .../ic_action_import_export_light.png | Bin 0 -> 896 bytes res/layout/download_playlist.xml | 13 ++++- res/layout/song_list_item.xml | 12 ++++- res/values/colors.xml | 2 + res/values/styles.xml | 2 + res/values/themes.xml | 4 ++ .../androidapp/activity/DownloadActivity.java | 51 ++++++++++++++++-- .../androidapp/view/EntryAdapter.java | 2 +- .../androidapp/view/SongListAdapter.java | 2 +- .../ultrasonic/androidapp/view/SongView.java | 5 +- 19 files changed, 131 insertions(+), 21 deletions(-) create mode 160000 drag-sort-listview create mode 100644 drag-sort-listview.iml create mode 100644 res/drawable-xxhdpi/ic_action_import_export_dark.png create mode 100644 res/drawable-xxhdpi/ic_action_import_export_light.png diff --git a/.gitmodules b/.gitmodules index 68b49e09..e1e7512a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ [submodule "pulltorefresh"] path = pulltorefresh url = git://github.com/chrisbanes/Android-PullToRefresh.git +[submodule "drag-sort-listview"] + path = drag-sort-listview + url = https://github.com/bauerca/drag-sort-listview diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 5cc19196..ead65380 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -2,8 +2,6 @@ - - diff --git a/.idea/modules.xml b/.idea/modules.xml index 97015b21..0c812c3e 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,6 +3,7 @@ + diff --git a/Subsonic-Android.iml b/Subsonic-Android.iml index f5676017..12768e7b 100644 --- a/Subsonic-Android.iml +++ b/Subsonic-Android.iml @@ -23,6 +23,7 @@ + diff --git a/drag-sort-listview b/drag-sort-listview new file mode 160000 index 00000000..c3cfccee --- /dev/null +++ b/drag-sort-listview @@ -0,0 +1 @@ +Subproject commit c3cfccee21676149dfdf8e803c0ec2eaebc6b841 diff --git a/drag-sort-listview.iml b/drag-sort-listview.iml new file mode 100644 index 00000000..a06ae8f0 --- /dev/null +++ b/drag-sort-listview.iml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/menudrawer.iml b/menudrawer.iml index 23044962..8937b1bb 100644 --- a/menudrawer.iml +++ b/menudrawer.iml @@ -3,10 +3,10 @@ - - - - + + + diff --git a/project.properties b/project.properties index 2c8cde28..926cf3ea 100644 --- a/project.properties +++ b/project.properties @@ -10,7 +10,8 @@ # Project target. target=android-19 android.library=false -android.library.reference.1=menudrawer +android.library.reference.1=menudrawer/menudrawer android.library.reference.2=pulltorefresh +android.library.reference.3=drag-sort-listview/library diff --git a/res/drawable-xxhdpi/ic_action_import_export_dark.png b/res/drawable-xxhdpi/ic_action_import_export_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2dccb24360cc2dc130cf3f2b3a02f56097606bb2 GIT binary patch literal 758 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m}YpoIEGZ*dNcQ|FH@k1o8;qbOj{VF7cg=Me18$gJz?*T z=}am5Zw@kPI7lsE&~0G)u)+m;!+q1wt9EYavZLj!^G|<^{jq)3DmRV}^#_q<;`{6Vs0fL1bQrul z{VwtNdb3S;yIV||4vF6P-ErBTFS5Hqnx#ehd+bMleih9xg^^cx4M^F6F$YB5Y-|2qU^w=<^2Xc&eS$7ofe|zRiKj?~^r|+BjC|AMo8(dw#iWcZ(zw zpZI^jvhqg1`sB5tfv$RW@zdul{1L(_&GIJC^o(ua@81SjclBu|gm+ttq(xm1UGnIC zwqg4rpVwB)(_$u{y!l7;gSoq{0|OHSBS(XZ%=AxAU$l1T)n`ui=Kj57fqC%$lSbD( z6F8Vy6c`vA7+4sX1Q<9R7%(^uO($Qj<0zkgXvx8i93MLGE#Lere?CK-0#KVk1B1ub z9~(aSmvwA;=`=QH|_IpxAkkp)6EY5pqScQ@%ANdM)vNhWABQ%F<)pM^_2_bg*w z(W1v0b8_>Fv)lokxkfKGdED1^b(k%3Ovh<%m%sv{J6$XC_%h8lrXA%7;4Ga~alLBm zZbt_R&h||!Hg|2)2|N(L_Vt@XvE9N8gvz$AJ9|tzdaA*t_lny8cAwak8=CR({?{(a lpfl{ZELkB5s6pq4Py$222c{COsdvGt%G1@)Wt~$(699!TKx_a2 literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_action_import_export_light.png b/res/drawable-xxhdpi/ic_action_import_export_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f054a68e6abba4319859c62466cc8c1c14229302 GIT binary patch literal 896 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3X(T978H@y_vHx|8{^t``n5XOB9%=E}hgUG9{#o&B`EX z*TqY{JUIyo&3}#Ayx4-Gc3pTh!S$7c`qh*L3ep;q83#SyFA-nc8+E+!&%FE9KkZI# zT72XDxxY2v&rN?ai3R8k5U@!!ka%-?lj!GkA6v7!_^|gWH&1@9v6<`l|EPw;_29?p zo2v5TzNJ`pTxH%hFYdZ@e4#IwaQ;WM>O(c- zd5!E5J-_EacRFt){fKpD#X(EC3pVU&hhkfnE!$n;u(^D{--h+mEnI>xzkkGOUeR!O z$NVX0*z-R&uuZW3xp>XIYZhD7kCz?c=3-e<|NZsc{a!ZLuWS(zT<0XZ;PRr62v=~7u= z-};uYRUWd^`|~YpdDfNOEzS6|W})YH6H{L%?bzLOTAq8K*~YP|WUke&-}2gqx0PmG zDm^}(+i>#d)m^*$Ro?#>bJkomn}JDzL4kqELEEPDY4eQbZ{Bw8j`t7?RdCpxqd)PO zRvd=|hZ6$}1B(NL10HHai~s(v9UHdjGld-dTszgg zf2o#_U5qvd-&Xf@7I66gcEo%W7^K@-k%QMylcNp`zCML_ie(ofG_T5^TTaYbdJgYEO?u# zBDX;4&$VmcHvP;AyfgjjYW?27iv$mJ6zC~s9L!ssvR&V*h|Kas4i{oK~#0uHpK<44Vrk|Iv@-cYeE0&g56 - + a:textFilterEnabled="true" + dslv:drag_handle_id="@+id/song_drag" + dslv:remove_enabled="true" + dslv:remove_mode="flingRemove" + dslv:fling_handle_id="@+id/song_drag" + dslv:drag_start_mode="onMove" + dslv:float_background_color="?attr/color_background" + dslv:float_alpha="0.7" /> + \ No newline at end of file diff --git a/res/layout/song_list_item.xml b/res/layout/song_list_item.xml index a43f13ff..9cfc7572 100644 --- a/res/layout/song_list_item.xml +++ b/res/layout/song_list_item.xml @@ -11,7 +11,7 @@ a:layout_height="fill_parent" a:checkMark="?attr/button_check_custom" a:gravity="center_vertical" - a:paddingLeft="1dip" /> + a:paddingLeft="3dip" /> @@ -25,4 +25,14 @@ a:paddingRight="3dip" a:src="?attr/star_hollow" /> + + \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index 6a1038ff..74af4813 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -18,4 +18,6 @@ #B0000000 #80000000 #FF555555 + #ff000000 + #fff3f3f3 \ No newline at end of file diff --git a/res/values/styles.xml b/res/values/styles.xml index 3466d4a5..a6cb48b9 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -88,6 +88,8 @@ + + diff --git a/res/values/themes.xml b/res/values/themes.xml index c8e5a79e..ce7a2c05 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -2,6 +2,7 @@ \ No newline at end of file diff --git a/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java b/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java index 8cc49c0c..c06bb26f 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/activity/DownloadActivity.java @@ -46,11 +46,11 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; -import android.widget.ListView; import android.widget.SeekBar; import android.widget.TextView; import android.widget.ViewFlipper; +import com.mobeta.android.dslv.DragSortListView; import com.thejoshwa.ultrasonic.androidapp.R; import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory; import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory.Entry; @@ -95,7 +95,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi private TextView albumTextView; private TextView artistTextView; private ImageView albumArtImageView; - private ListView playlistView; + private DragSortListView playlistView; private TextView positionTextView; private TextView downloadTrackTextView; private TextView downloadTotalDurationTextView; @@ -153,7 +153,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi downloadTotalDurationTextView = (TextView) findViewById(R.id.download_total_duration); durationTextView = (TextView) findViewById(R.id.download_duration); progressBar = (SeekBar) findViewById(R.id.download_progress_bar); - playlistView = (ListView) findViewById(R.id.download_list); + playlistView = (DragSortListView) findViewById(R.id.download_list); final AutoRepeatButton previousButton = (AutoRepeatButton) findViewById(R.id.download_previous); final AutoRepeatButton nextButton = (AutoRepeatButton) findViewById(R.id.download_next); pauseButton = findViewById(R.id.download_pause); @@ -974,7 +974,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi if (song != null) { - entry = song.getSong(); + entry = song.getSong(); } switch (menuItemId) @@ -1174,7 +1174,48 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi final List list = downloadService.getSongs(); emptyTextView.setText(R.string.download_empty); - playlistView.setAdapter(new SongListAdapter(this, list)); + final SongListAdapter adapter = new SongListAdapter(this, list); + playlistView.setAdapter(adapter); + + playlistView.setDragSortListener(new DragSortListView.DragSortListener() + { + @Override + public void drop(int from, int to) + { + if (from != to) + { + DownloadFile item = adapter.getItem(from); + adapter.remove(item); + adapter.insert(item, to); + onDownloadListChanged(); + onCurrentChanged(); + } + } + + @Override + public void drag(int from, int to) + { + + } + + + @Override + public void remove(int which) + { + DownloadFile item = adapter.getItem(which); + DownloadFile currentPlaying = getDownloadService().getCurrentPlaying(); + + if (currentPlaying == item) + { + getDownloadService().next(); + } + + adapter.remove(item); + onDownloadListChanged(); + onCurrentChanged(); + } + }); + emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE); currentRevision = downloadService.getDownloadListUpdateRevision(); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/EntryAdapter.java b/src/com/thejoshwa/ultrasonic/androidapp/view/EntryAdapter.java index 8bdbc243..65ea5d36 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/EntryAdapter.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/EntryAdapter.java @@ -98,7 +98,7 @@ public class EntryAdapter extends ArrayAdapter view = new SongView(activity); } - view.setSong(entry, checkable); + view.setSong(entry, checkable, false); return view; } } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/SongListAdapter.java b/src/com/thejoshwa/ultrasonic/androidapp/view/SongListAdapter.java index a8d9dcb5..80ef62bc 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/SongListAdapter.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/SongListAdapter.java @@ -46,7 +46,7 @@ public class SongListAdapter extends ArrayAdapter view = new SongView(this.context); } - view.setSong(entry, false); + view.setSong(entry, false, true); return view; } } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java b/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java index d721d30c..9337dc86 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java @@ -61,6 +61,7 @@ public class SongView extends UpdateView implements Checkable private CheckedTextView checkedTextView; private ImageView starImageView; + private ImageView songDragImageView; private TextView titleTextView; private TextView statusTextView; private Entry song; @@ -125,7 +126,7 @@ public class SongView extends UpdateView implements Checkable return this.song; } - protected void setSong(final Entry song, boolean checkable) + protected void setSong(final Entry song, boolean checkable, boolean dragable) { updateBackground(); @@ -140,6 +141,7 @@ public class SongView extends UpdateView implements Checkable checkedTextView = (CheckedTextView) findViewById(R.id.song_check); starImageView = (ImageView) findViewById(R.id.song_star); + songDragImageView = (ImageView) findViewById(R.id.song_drag); TextView trackTextView = (TextView) findViewById(R.id.song_track); titleTextView = (TextView) findViewById(R.id.song_title); TextView artistTextView = (TextView) findViewById(R.id.song_artist); @@ -204,6 +206,7 @@ public class SongView extends UpdateView implements Checkable } checkedTextView.setVisibility(checkable && !song.isVideo() ? View.VISIBLE : View.GONE); + songDragImageView.setVisibility(dragable ? View.VISIBLE : View.GONE); if (Util.isOffline(this.context)) {