Extend incremental search to albums and tracks #152
@ -77,7 +77,7 @@ impl<MH: IMusicHoard> IAppInteractBrowse for AppMachine<MH, AppBrowse> {
|
|||||||
let orig = ListSelection::get(&self.inner.selection);
|
let orig = ListSelection::get(&self.inner.selection);
|
||||||
self.inner
|
self.inner
|
||||||
.selection
|
.selection
|
||||||
.reset_artist(self.inner.music_hoard.get_collection());
|
.reset(self.inner.music_hoard.get_collection());
|
||||||
AppMachine::search(self.inner, orig).into()
|
AppMachine::search(self.inner, orig).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use aho_corasick::AhoCorasick;
|
use aho_corasick::AhoCorasick;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use musichoard::collection::artist::Artist;
|
use musichoard::collection::{album::Album, artist::Artist, track::Track};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
machine::{App, AppInner, AppMachine},
|
machine::{App, AppInner, AppMachine},
|
||||||
selection::ListSelection,
|
selection::ListSelection,
|
||||||
AppPublic, AppState, IAppInteractSearch,
|
AppPublic, AppState, Category, IAppInteractSearch,
|
||||||
},
|
},
|
||||||
lib::IMusicHoard,
|
lib::IMusicHoard,
|
||||||
};
|
};
|
||||||
@ -67,7 +67,7 @@ impl<MH: IMusicHoard> IAppInteractSearch for AppMachine<MH, AppSearch> {
|
|||||||
|
|
||||||
fn append_character(mut self, ch: char) -> Self::APP {
|
fn append_character(mut self, ch: char) -> Self::APP {
|
||||||
self.state.string.push(ch);
|
self.state.string.push(ch);
|
||||||
let index = self.inner.selection.artist.state.list.selected();
|
let index = self.inner.selection.selected();
|
||||||
self.state.memo.push(AppSearchMemo { index, char: true });
|
self.state.memo.push(AppSearchMemo { index, char: true });
|
||||||
self.incremental_search(false);
|
self.incremental_search(false);
|
||||||
self.into()
|
self.into()
|
||||||
@ -75,7 +75,7 @@ impl<MH: IMusicHoard> IAppInteractSearch for AppMachine<MH, AppSearch> {
|
|||||||
|
|
||||||
fn search_next(mut self) -> Self::APP {
|
fn search_next(mut self) -> Self::APP {
|
||||||
if !self.state.string.is_empty() {
|
if !self.state.string.is_empty() {
|
||||||
let index = self.inner.selection.artist.state.list.selected();
|
let index = self.inner.selection.selected();
|
||||||
self.state.memo.push(AppSearchMemo { index, char: false });
|
self.state.memo.push(AppSearchMemo { index, char: false });
|
||||||
self.incremental_search(true);
|
self.incremental_search(true);
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ impl<MH: IMusicHoard> IAppInteractSearch for AppMachine<MH, AppSearch> {
|
|||||||
if memo.char {
|
if memo.char {
|
||||||
self.state.string.pop();
|
self.state.string.pop();
|
||||||
}
|
}
|
||||||
self.inner.selection.select_artist(collection, memo.index);
|
self.inner.selection.select(collection, memo.index);
|
||||||
}
|
}
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
@ -109,12 +109,13 @@ impl<MH: IMusicHoard> IAppInteractSearch for AppMachine<MH, AppSearch> {
|
|||||||
|
|
||||||
trait IAppInteractSearchPrivate {
|
trait IAppInteractSearchPrivate {
|
||||||
fn incremental_search(&mut self, next: bool);
|
fn incremental_search(&mut self, next: bool);
|
||||||
fn incremental_search_predicate(
|
fn search_category<T, P>(list: &[T], index: usize, next: bool, pred: P) -> Option<usize>
|
||||||
case_sensitive: bool,
|
where
|
||||||
char_sensitive: bool,
|
P: FnMut(&T) -> bool;
|
||||||
search_name: &str,
|
fn predicate_artists(case_sens: bool, char_sens: bool, search: &str, probe: &Artist) -> bool;
|
||||||
probe: &Artist,
|
fn predicate_albums(case_sens: bool, char_sens: bool, search: &str, probe: &Album) -> bool;
|
||||||
) -> bool;
|
fn predicate_tracks(case_sens: bool, char_sens: bool, search: &str, probe: &Track) -> bool;
|
||||||
|
fn predicate_title(case_sens: bool, char_sens: bool, search: &str, title: &str) -> bool;
|
||||||
|
|
||||||
fn is_case_sensitive(artist_name: &str) -> bool;
|
fn is_case_sensitive(artist_name: &str) -> bool;
|
||||||
fn is_char_sensitive(artist_name: &str) -> bool;
|
fn is_char_sensitive(artist_name: &str) -> bool;
|
||||||
@ -123,50 +124,102 @@ trait IAppInteractSearchPrivate {
|
|||||||
|
|
||||||
impl<MH: IMusicHoard> IAppInteractSearchPrivate for AppMachine<MH, AppSearch> {
|
impl<MH: IMusicHoard> IAppInteractSearchPrivate for AppMachine<MH, AppSearch> {
|
||||||
fn incremental_search(&mut self, next: bool) {
|
fn incremental_search(&mut self, next: bool) {
|
||||||
let artists = self.inner.music_hoard.get_collection();
|
let collection = self.inner.music_hoard.get_collection();
|
||||||
let artist_name = &self.state.string;
|
let search_name = &self.state.string;
|
||||||
|
|
||||||
let sel = &mut self.inner.selection;
|
let sel = &mut self.inner.selection;
|
||||||
if let Some(mut index) = sel.selected_artist() {
|
if let Some(index) = sel.selected() {
|
||||||
let case_sensitive = Self::is_case_sensitive(artist_name);
|
let case_sensitive = Self::is_case_sensitive(search_name);
|
||||||
let char_sensitive = Self::is_char_sensitive(artist_name);
|
let char_sensitive = Self::is_char_sensitive(search_name);
|
||||||
let search = Self::normalize_search(artist_name, !case_sensitive, !char_sensitive);
|
let search = Self::normalize_search(search_name, !case_sensitive, !char_sensitive);
|
||||||
|
|
||||||
if next && ((index + 1) < artists.len()) {
|
let result = match sel.active {
|
||||||
|
Category::Artist => {
|
||||||
|
let artists = collection;
|
||||||
|
Self::search_category(artists, index, next, |probe| {
|
||||||
|
Self::predicate_artists(case_sensitive, char_sensitive, &search, probe)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Category::Album => {
|
||||||
|
let artists = collection;
|
||||||
|
let albums = sel
|
||||||
|
.artist
|
||||||
|
.state
|
||||||
|
.list
|
||||||
|
.selected()
|
||||||
|
.map(|i| &artists[i].albums)
|
||||||
|
.unwrap();
|
||||||
|
Self::search_category(albums, index, next, |probe| {
|
||||||
|
Self::predicate_albums(case_sensitive, char_sensitive, &search, probe)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Category::Track => {
|
||||||
|
let artists = collection;
|
||||||
|
let albums = sel
|
||||||
|
.artist
|
||||||
|
.state
|
||||||
|
.list
|
||||||
|
.selected()
|
||||||
|
.map(|i| &artists[i].albums)
|
||||||
|
.unwrap();
|
||||||
|
let tracks = sel
|
||||||
|
.artist
|
||||||
|
.album
|
||||||
|
.state
|
||||||
|
.list
|
||||||
|
.selected()
|
||||||
|
.map(|i| &albums[i].tracks)
|
||||||
|
.unwrap();
|
||||||
|
Self::search_category(tracks, index, next, |probe| {
|
||||||
|
Self::predicate_tracks(case_sensitive, char_sensitive, &search, probe)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if result.is_some() {
|
||||||
|
sel.select(collection, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_category<T, P>(list: &[T], mut index: usize, next: bool, pred: P) -> Option<usize>
|
||||||
|
where
|
||||||
|
P: FnMut(&T) -> bool,
|
||||||
|
{
|
||||||
|
if next && ((index + 1) < list.len()) {
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
let slice = &artists[index..];
|
let slice = &list[index..];
|
||||||
|
let result = slice.iter().position(pred);
|
||||||
let result = slice.iter().position(|probe| {
|
result.map(|slice_index| index + slice_index)
|
||||||
Self::incremental_search_predicate(case_sensitive, char_sensitive, &search, probe)
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(slice_index) = result {
|
|
||||||
sel.select_artist(artists, Some(index + slice_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn incremental_search_predicate(
|
fn predicate_artists(case_sens: bool, char_sens: bool, search: &str, probe: &Artist) -> bool {
|
||||||
case_sensitive: bool,
|
let name = Self::normalize_search(&probe.id.name, !case_sens, !char_sens);
|
||||||
char_sensitive: bool,
|
let mut result = name.starts_with(search);
|
||||||
search_name: &str,
|
|
||||||
probe: &Artist,
|
|
||||||
) -> bool {
|
|
||||||
let name = Self::normalize_search(&probe.id.name, !case_sensitive, !char_sensitive);
|
|
||||||
let mut result = name.starts_with(search_name);
|
|
||||||
|
|
||||||
if let Some(ref probe_sort) = probe.sort {
|
if let Some(ref probe_sort) = probe.sort {
|
||||||
if !result {
|
if !result {
|
||||||
let name =
|
let name = Self::normalize_search(&probe_sort.name, !case_sens, !char_sens);
|
||||||
Self::normalize_search(&probe_sort.name, !case_sensitive, !char_sensitive);
|
result = name.starts_with(search);
|
||||||
result = name.starts_with(search_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn predicate_albums(case_sens: bool, char_sens: bool, search: &str, probe: &Album) -> bool {
|
||||||
|
Self::predicate_title(case_sens, char_sens, search, &probe.id.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn predicate_tracks(case_sens: bool, char_sens: bool, search: &str, probe: &Track) -> bool {
|
||||||
|
Self::predicate_title(case_sens, char_sens, search, &probe.id.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn predicate_title(case_sens: bool, char_sens: bool, search: &str, title: &str) -> bool {
|
||||||
|
Self::normalize_search(title, !case_sens, !char_sens).starts_with(search)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_case_sensitive(artist_name: &str) -> bool {
|
fn is_case_sensitive(artist_name: &str) -> bool {
|
||||||
artist_name
|
artist_name
|
||||||
.chars()
|
.chars()
|
||||||
|
@ -80,20 +80,6 @@ impl Selection {
|
|||||||
self.artist.reinitialise(artists, selected.artist);
|
self.artist.reinitialise(artists, selected.artist);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_artist(&mut self, artists: &[Artist], index: Option<usize>) {
|
|
||||||
self.artist.select(artists, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn selected_artist(&self) -> Option<usize> {
|
|
||||||
self.artist.selected()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset_artist(&mut self, artists: &[Artist]) {
|
|
||||||
if self.artist.state.list.selected() != Some(0) {
|
|
||||||
self.select_by_id(artists, IdSelection { artist: None });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn increment_category(&mut self) {
|
pub fn increment_category(&mut self) {
|
||||||
self.active = match self.active {
|
self.active = match self.active {
|
||||||
Category::Artist => Category::Album,
|
Category::Artist => Category::Album,
|
||||||
@ -110,6 +96,66 @@ impl Selection {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn select(&mut self, collection: &Collection, index: Option<usize>) {
|
||||||
|
match self.active {
|
||||||
|
Category::Artist => self.select_artist(collection, index),
|
||||||
|
Category::Album => self.select_album(collection, index),
|
||||||
|
Category::Track => self.select_track(collection, index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_artist(&mut self, artists: &[Artist], index: Option<usize>) {
|
||||||
|
self.artist.select(artists, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_album(&mut self, artists: &[Artist], index: Option<usize>) {
|
||||||
|
self.artist.select_album(artists, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_track(&mut self, artists: &[Artist], index: Option<usize>) {
|
||||||
|
self.artist.select_track(artists, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn selected(&self) -> Option<usize> {
|
||||||
|
match self.active {
|
||||||
|
Category::Artist => self.selected_artist(),
|
||||||
|
Category::Album => self.selected_album(),
|
||||||
|
Category::Track => self.selected_track(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_artist(&self) -> Option<usize> {
|
||||||
|
self.artist.selected()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_album(&self) -> Option<usize> {
|
||||||
|
self.artist.selected_album()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_track(&self) -> Option<usize> {
|
||||||
|
self.artist.selected_track()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self, collection: &Collection) {
|
||||||
|
match self.active {
|
||||||
|
Category::Artist => self.reset_artist(collection),
|
||||||
|
Category::Album => self.reset_album(collection),
|
||||||
|
Category::Track => self.reset_track(collection),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_artist(&mut self, artists: &[Artist]) {
|
||||||
|
self.artist.reset(artists);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_album(&mut self, artists: &[Artist]) {
|
||||||
|
self.artist.reset_album(artists);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_track(&mut self, artists: &[Artist]) {
|
||||||
|
self.artist.reset_track(artists);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn increment_selection(&mut self, collection: &Collection, delta: Delta) {
|
pub fn increment_selection(&mut self, collection: &Collection, delta: Delta) {
|
||||||
match self.active {
|
match self.active {
|
||||||
Category::Artist => self.increment_artist(collection, delta),
|
Category::Artist => self.increment_artist(collection, delta),
|
||||||
@ -118,6 +164,18 @@ impl Selection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn increment_artist(&mut self, artists: &[Artist], delta: Delta) {
|
||||||
|
self.artist.increment(artists, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increment_album(&mut self, artists: &[Artist], delta: Delta) {
|
||||||
|
self.artist.increment_album(artists, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increment_track(&mut self, artists: &[Artist], delta: Delta) {
|
||||||
|
self.artist.increment_track(artists, delta);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn decrement_selection(&mut self, collection: &Collection, delta: Delta) {
|
pub fn decrement_selection(&mut self, collection: &Collection, delta: Delta) {
|
||||||
match self.active {
|
match self.active {
|
||||||
Category::Artist => self.decrement_artist(collection, delta),
|
Category::Artist => self.decrement_artist(collection, delta),
|
||||||
@ -126,26 +184,14 @@ impl Selection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment_artist(&mut self, artists: &[Artist], delta: Delta) {
|
|
||||||
self.artist.increment(artists, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrement_artist(&mut self, artists: &[Artist], delta: Delta) {
|
fn decrement_artist(&mut self, artists: &[Artist], delta: Delta) {
|
||||||
self.artist.decrement(artists, delta);
|
self.artist.decrement(artists, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment_album(&mut self, artists: &[Artist], delta: Delta) {
|
|
||||||
self.artist.increment_album(artists, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrement_album(&mut self, artists: &[Artist], delta: Delta) {
|
fn decrement_album(&mut self, artists: &[Artist], delta: Delta) {
|
||||||
self.artist.decrement_album(artists, delta);
|
self.artist.decrement_album(artists, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment_track(&mut self, artists: &[Artist], delta: Delta) {
|
|
||||||
self.artist.increment_track(artists, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrement_track(&mut self, artists: &[Artist], delta: Delta) {
|
fn decrement_track(&mut self, artists: &[Artist], delta: Delta) {
|
||||||
self.artist.decrement_track(artists, delta);
|
self.artist.decrement_track(artists, delta);
|
||||||
}
|
}
|
||||||
@ -197,6 +243,14 @@ impl ArtistSelection {
|
|||||||
self.state.list.selected()
|
self.state.list.selected()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn selected_album(&self) -> Option<usize> {
|
||||||
|
self.album.selected()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_track(&self) -> Option<usize> {
|
||||||
|
self.album.selected_track()
|
||||||
|
}
|
||||||
|
|
||||||
fn select(&mut self, artists: &[Artist], to: Option<usize>) {
|
fn select(&mut self, artists: &[Artist], to: Option<usize>) {
|
||||||
match to {
|
match to {
|
||||||
Some(to) => self.select_to(artists, to),
|
Some(to) => self.select_to(artists, to),
|
||||||
@ -204,6 +258,18 @@ impl ArtistSelection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_album(&mut self, artists: &[Artist], to: Option<usize>) {
|
||||||
|
if let Some(index) = self.state.list.selected() {
|
||||||
|
self.album.select(&artists[index].albums, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_track(&mut self, artists: &[Artist], to: Option<usize>) {
|
||||||
|
if let Some(index) = self.state.list.selected() {
|
||||||
|
self.album.select_track(&artists[index].albums, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn select_to(&mut self, artists: &[Artist], mut to: usize) {
|
fn select_to(&mut self, artists: &[Artist], mut to: usize) {
|
||||||
to = cmp::min(to, artists.len() - 1);
|
to = cmp::min(to, artists.len() - 1);
|
||||||
if self.state.list.selected() != Some(to) {
|
if self.state.list.selected() != Some(to) {
|
||||||
@ -212,6 +278,24 @@ impl ArtistSelection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self, artists: &[Artist]) {
|
||||||
|
if self.state.list.selected() != Some(0) {
|
||||||
|
self.reinitialise(artists, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_album(&mut self, artists: &[Artist]) {
|
||||||
|
if let Some(index) = self.state.list.selected() {
|
||||||
|
self.album.reset(&artists[index].albums);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_track(&mut self, artists: &[Artist]) {
|
||||||
|
if let Some(index) = self.state.list.selected() {
|
||||||
|
self.album.reset_track(&artists[index].albums);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn increment_by(&mut self, artists: &[Artist], by: usize) {
|
fn increment_by(&mut self, artists: &[Artist], by: usize) {
|
||||||
if let Some(index) = self.state.list.selected() {
|
if let Some(index) = self.state.list.selected() {
|
||||||
let result = index.saturating_add(by);
|
let result = index.saturating_add(by);
|
||||||
@ -303,6 +387,47 @@ impl AlbumSelection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn selected(&self) -> Option<usize> {
|
||||||
|
self.state.list.selected()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selected_track(&self) -> Option<usize> {
|
||||||
|
self.track.selected()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select(&mut self, albums: &[Album], to: Option<usize>) {
|
||||||
|
match to {
|
||||||
|
Some(to) => self.select_to(albums, to),
|
||||||
|
None => self.state.list.select(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_track(&mut self, albums: &[Album], to: Option<usize>) {
|
||||||
|
if let Some(index) = self.state.list.selected() {
|
||||||
|
self.track.select(&albums[index].tracks, to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_to(&mut self, albums: &[Album], mut to: usize) {
|
||||||
|
to = cmp::min(to, albums.len() - 1);
|
||||||
|
if self.state.list.selected() != Some(to) {
|
||||||
|
self.state.list.select(Some(to));
|
||||||
|
self.track = TrackSelection::initialise(&albums[to].tracks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self, albums: &[Album]) {
|
||||||
|
if self.state.list.selected() != Some(0) {
|
||||||
|
self.reinitialise(albums, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_track(&mut self, albums: &[Album]) {
|
||||||
|
if let Some(index) = self.state.list.selected() {
|
||||||
|
self.track.reset(&albums[index].tracks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn increment_by(&mut self, albums: &[Album], by: usize) {
|
fn increment_by(&mut self, albums: &[Album], by: usize) {
|
||||||
if let Some(index) = self.state.list.selected() {
|
if let Some(index) = self.state.list.selected() {
|
||||||
let mut result = index.saturating_add(by);
|
let mut result = index.saturating_add(by);
|
||||||
@ -377,6 +502,28 @@ impl TrackSelection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn selected(&self) -> Option<usize> {
|
||||||
|
self.state.list.selected()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select(&mut self, tracks: &[Track], to: Option<usize>) {
|
||||||
|
match to {
|
||||||
|
Some(to) => self.select_to(tracks, to),
|
||||||
|
None => self.state.list.select(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_to(&mut self, tracks: &[Track], mut to: usize) {
|
||||||
|
to = cmp::min(to, tracks.len() - 1);
|
||||||
|
self.state.list.select(Some(to));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self, tracks: &[Track]) {
|
||||||
|
if self.state.list.selected() != Some(0) {
|
||||||
|
self.reinitialise(tracks, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn increment_by(&mut self, tracks: &[Track], by: usize) {
|
fn increment_by(&mut self, tracks: &[Track], by: usize) {
|
||||||
if let Some(index) = self.state.list.selected() {
|
if let Some(index) = self.state.list.selected() {
|
||||||
let mut result = index.saturating_add(by);
|
let mut result = index.saturating_add(by);
|
||||||
|
Loading…
Reference in New Issue
Block a user