Selected item is always at the bottom of list #41
327
src/tui/ui.rs
327
src/tui/ui.rs
@ -13,44 +13,44 @@ use ratatui::{
|
|||||||
use super::Error;
|
use super::Error;
|
||||||
|
|
||||||
struct TrackSelection {
|
struct TrackSelection {
|
||||||
selection: ListState,
|
state: ListState,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AlbumSelection {
|
struct AlbumSelection {
|
||||||
selection: ListState,
|
state: ListState,
|
||||||
track: TrackSelection,
|
track: TrackSelection,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArtistSelection {
|
struct ArtistSelection {
|
||||||
selection: ListState,
|
state: ListState,
|
||||||
album: AlbumSelection,
|
album: AlbumSelection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrackSelection {
|
impl TrackSelection {
|
||||||
fn initialise(tracks: Option<&[Track]>) -> Self {
|
fn initialise(tracks: Option<&[Track]>) -> Self {
|
||||||
let mut selection = ListState::default();
|
let mut state = ListState::default();
|
||||||
if let Some(tracks) = tracks {
|
if let Some(tracks) = tracks {
|
||||||
selection.select(if !tracks.is_empty() { Some(0) } else { None });
|
state.select(if !tracks.is_empty() { Some(0) } else { None });
|
||||||
} else {
|
} else {
|
||||||
selection.select(None);
|
state.select(None);
|
||||||
};
|
};
|
||||||
TrackSelection { selection }
|
TrackSelection { state }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment(&mut self, tracks: &[Track]) {
|
fn increment(&mut self, tracks: &[Track]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
if let Some(result) = index.checked_add(1) {
|
if let Some(result) = index.checked_add(1) {
|
||||||
if result < tracks.len() {
|
if result < tracks.len() {
|
||||||
self.selection.select(Some(result));
|
self.state.select(Some(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrement(&mut self, _tracks: &[Track]) {
|
fn decrement(&mut self, _tracks: &[Track]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
if let Some(result) = index.checked_sub(1) {
|
if let Some(result) = index.checked_sub(1) {
|
||||||
self.selection.select(Some(result));
|
self.state.select(Some(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,23 +58,23 @@ impl TrackSelection {
|
|||||||
|
|
||||||
impl AlbumSelection {
|
impl AlbumSelection {
|
||||||
fn initialise(albums: Option<&[Album]>) -> Self {
|
fn initialise(albums: Option<&[Album]>) -> Self {
|
||||||
let mut selection = ListState::default();
|
let mut state = ListState::default();
|
||||||
let track: TrackSelection;
|
let track: TrackSelection;
|
||||||
if let Some(albums) = albums {
|
if let Some(albums) = albums {
|
||||||
selection.select(if !albums.is_empty() { Some(0) } else { None });
|
state.select(if !albums.is_empty() { Some(0) } else { None });
|
||||||
track = TrackSelection::initialise(albums.get(0).map(|a| a.tracks.as_slice()));
|
track = TrackSelection::initialise(albums.get(0).map(|a| a.tracks.as_slice()));
|
||||||
} else {
|
} else {
|
||||||
selection.select(None);
|
state.select(None);
|
||||||
track = TrackSelection::initialise(None);
|
track = TrackSelection::initialise(None);
|
||||||
}
|
}
|
||||||
AlbumSelection { selection, track }
|
AlbumSelection { state, track }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment(&mut self, albums: &[Album]) {
|
fn increment(&mut self, albums: &[Album]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
if let Some(result) = index.checked_add(1) {
|
if let Some(result) = index.checked_add(1) {
|
||||||
if result < albums.len() {
|
if result < albums.len() {
|
||||||
self.selection.select(Some(result));
|
self.state.select(Some(result));
|
||||||
self.track = TrackSelection::initialise(Some(&albums[result].tracks));
|
self.track = TrackSelection::initialise(Some(&albums[result].tracks));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,22 +82,22 @@ impl AlbumSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn increment_track(&mut self, albums: &[Album]) {
|
fn increment_track(&mut self, albums: &[Album]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
self.track.increment(&albums[index].tracks);
|
self.track.increment(&albums[index].tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrement(&mut self, albums: &[Album]) {
|
fn decrement(&mut self, albums: &[Album]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
if let Some(result) = index.checked_sub(1) {
|
if let Some(result) = index.checked_sub(1) {
|
||||||
self.selection.select(Some(result));
|
self.state.select(Some(result));
|
||||||
self.track = TrackSelection::initialise(Some(&albums[result].tracks));
|
self.track = TrackSelection::initialise(Some(&albums[result].tracks));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrement_track(&mut self, albums: &[Album]) {
|
fn decrement_track(&mut self, albums: &[Album]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
self.track.decrement(&albums[index].tracks);
|
self.track.decrement(&albums[index].tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,23 +105,23 @@ impl AlbumSelection {
|
|||||||
|
|
||||||
impl ArtistSelection {
|
impl ArtistSelection {
|
||||||
fn initialise(artists: Option<&[Artist]>) -> Self {
|
fn initialise(artists: Option<&[Artist]>) -> Self {
|
||||||
let mut selection = ListState::default();
|
let mut state = ListState::default();
|
||||||
let album: AlbumSelection;
|
let album: AlbumSelection;
|
||||||
if let Some(artists) = artists {
|
if let Some(artists) = artists {
|
||||||
selection.select(if !artists.is_empty() { Some(0) } else { None });
|
state.select(if !artists.is_empty() { Some(0) } else { None });
|
||||||
album = AlbumSelection::initialise(artists.get(0).map(|a| a.albums.as_slice()));
|
album = AlbumSelection::initialise(artists.get(0).map(|a| a.albums.as_slice()));
|
||||||
} else {
|
} else {
|
||||||
selection.select(None);
|
state.select(None);
|
||||||
album = AlbumSelection::initialise(None);
|
album = AlbumSelection::initialise(None);
|
||||||
}
|
}
|
||||||
ArtistSelection { selection, album }
|
ArtistSelection { state, album }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment(&mut self, artists: &[Artist]) {
|
fn increment(&mut self, artists: &[Artist]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
if let Some(result) = index.checked_add(1) {
|
if let Some(result) = index.checked_add(1) {
|
||||||
if result < artists.len() {
|
if result < artists.len() {
|
||||||
self.selection.select(Some(result));
|
self.state.select(Some(result));
|
||||||
self.album = AlbumSelection::initialise(Some(&artists[result].albums));
|
self.album = AlbumSelection::initialise(Some(&artists[result].albums));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,34 +129,34 @@ impl ArtistSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn increment_album(&mut self, artists: &[Artist]) {
|
fn increment_album(&mut self, artists: &[Artist]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
self.album.increment(&artists[index].albums);
|
self.album.increment(&artists[index].albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment_track(&mut self, artists: &[Artist]) {
|
fn increment_track(&mut self, artists: &[Artist]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
self.album.increment_track(&artists[index].albums);
|
self.album.increment_track(&artists[index].albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrement(&mut self, artists: &[Artist]) {
|
fn decrement(&mut self, artists: &[Artist]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
if let Some(result) = index.checked_sub(1) {
|
if let Some(result) = index.checked_sub(1) {
|
||||||
self.selection.select(Some(result));
|
self.state.select(Some(result));
|
||||||
self.album = AlbumSelection::initialise(Some(&artists[result].albums));
|
self.album = AlbumSelection::initialise(Some(&artists[result].albums));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrement_album(&mut self, artists: &[Artist]) {
|
fn decrement_album(&mut self, artists: &[Artist]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
self.album.decrement(&artists[index].albums);
|
self.album.decrement(&artists[index].albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrement_track(&mut self, artists: &[Artist]) {
|
fn decrement_track(&mut self, artists: &[Artist]) {
|
||||||
if let Some(index) = self.selection.selected() {
|
if let Some(index) = self.state.selected() {
|
||||||
self.album.decrement_track(&artists[index].albums);
|
self.album.decrement_track(&artists[index].albums);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,13 +247,11 @@ pub struct MhUi<CM> {
|
|||||||
|
|
||||||
struct ArtistArea {
|
struct ArtistArea {
|
||||||
list: Rect,
|
list: Rect,
|
||||||
album: AlbumArea,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AlbumArea {
|
struct AlbumArea {
|
||||||
list: Rect,
|
list: Rect,
|
||||||
info: Rect,
|
info: Rect,
|
||||||
track: TrackArea,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TrackArea {
|
struct TrackArea {
|
||||||
@ -261,32 +259,14 @@ struct TrackArea {
|
|||||||
info: Rect,
|
info: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArtistState<'a> {
|
struct FrameArea {
|
||||||
list: List<'a>,
|
artist: ArtistArea,
|
||||||
|
album: AlbumArea,
|
||||||
|
track: TrackArea,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AlbumState<'a> {
|
impl FrameArea {
|
||||||
list: List<'a>,
|
fn new(frame: Rect) -> FrameArea {
|
||||||
info: Paragraph<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TrackState<'a> {
|
|
||||||
list: List<'a>,
|
|
||||||
info: Paragraph<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<CM: CollectionManager> MhUi<CM> {
|
|
||||||
pub fn new(mut collection_manager: CM) -> Result<Self, Error> {
|
|
||||||
collection_manager.rescan_library()?;
|
|
||||||
let selection = Selection::new(Some(collection_manager.get_collection()));
|
|
||||||
Ok(MhUi {
|
|
||||||
collection_manager,
|
|
||||||
selection,
|
|
||||||
running: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct_areas(frame: Rect) -> ArtistArea {
|
|
||||||
let width_one_third = frame.width / 3;
|
let width_one_third = frame.width / 3;
|
||||||
let height_one_third = frame.height / 3;
|
let height_one_third = frame.height / 3;
|
||||||
|
|
||||||
@ -330,20 +310,28 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
height: panel_height_bottom,
|
height: panel_height_bottom,
|
||||||
};
|
};
|
||||||
|
|
||||||
ArtistArea {
|
FrameArea {
|
||||||
list: artist_list,
|
artist: ArtistArea { list: artist_list },
|
||||||
album: AlbumArea {
|
album: AlbumArea {
|
||||||
list: album_list,
|
list: album_list,
|
||||||
info: album_info,
|
info: album_info,
|
||||||
track: TrackArea {
|
},
|
||||||
list: track_list,
|
track: TrackArea {
|
||||||
info: track_info,
|
list: track_list,
|
||||||
},
|
info: track_info,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn construct_artist_state(artists: &[Artist]) -> ArtistState {
|
struct ArtistState<'a, 'b> {
|
||||||
|
active: bool,
|
||||||
|
list: List<'a>,
|
||||||
|
state: &'b mut ListState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ArtistState<'a, 'b> {
|
||||||
|
fn new(active: bool, artists: &'a [Artist], state: &'b mut ListState) -> ArtistState<'a, 'b> {
|
||||||
let list = List::new(
|
let list = List::new(
|
||||||
artists
|
artists
|
||||||
.iter()
|
.iter()
|
||||||
@ -351,10 +339,23 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
.collect::<Vec<ListItem>>(),
|
.collect::<Vec<ListItem>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
ArtistState { list }
|
ArtistState {
|
||||||
|
active,
|
||||||
|
list,
|
||||||
|
state,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn construct_album_state(albums: &[Album], selected: Option<usize>) -> AlbumState {
|
struct AlbumState<'a, 'b> {
|
||||||
|
active: bool,
|
||||||
|
list: List<'a>,
|
||||||
|
state: &'b mut ListState,
|
||||||
|
info: Paragraph<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> AlbumState<'a, 'b> {
|
||||||
|
fn new(active: bool, albums: &'a [Album], state: &'b mut ListState) -> AlbumState<'a, 'b> {
|
||||||
let list = List::new(
|
let list = List::new(
|
||||||
albums
|
albums
|
||||||
.iter()
|
.iter()
|
||||||
@ -362,7 +363,7 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
.collect::<Vec<ListItem>>(),
|
.collect::<Vec<ListItem>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let album = selected.map(|i| &albums[i]);
|
let album = state.selected().map(|i| &albums[i]);
|
||||||
let info = Paragraph::new(format!(
|
let info = Paragraph::new(format!(
|
||||||
"Title: {}\n\
|
"Title: {}\n\
|
||||||
Year: {}",
|
Year: {}",
|
||||||
@ -372,10 +373,24 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
.unwrap_or_else(|| "".to_string()),
|
.unwrap_or_else(|| "".to_string()),
|
||||||
));
|
));
|
||||||
|
|
||||||
AlbumState { list, info }
|
AlbumState {
|
||||||
|
active,
|
||||||
|
list,
|
||||||
|
state,
|
||||||
|
info,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn construct_track_state(tracks: &[Track], selected: Option<usize>) -> TrackState {
|
struct TrackState<'a, 'b> {
|
||||||
|
active: bool,
|
||||||
|
list: List<'a>,
|
||||||
|
state: &'b mut ListState,
|
||||||
|
info: Paragraph<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> TrackState<'a, 'b> {
|
||||||
|
fn new(active: bool, tracks: &'a [Track], state: &'b mut ListState) -> TrackState<'a, 'b> {
|
||||||
let list = List::new(
|
let list = List::new(
|
||||||
tracks
|
tracks
|
||||||
.iter()
|
.iter()
|
||||||
@ -383,12 +398,12 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
.collect::<Vec<ListItem>>(),
|
.collect::<Vec<ListItem>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let track = selected.map(|i| &tracks[i]);
|
let track = state.selected().map(|i| &tracks[i]);
|
||||||
let info = Paragraph::new(format!(
|
let info = Paragraph::new(format!(
|
||||||
"Track: {}\n\
|
"Track: {}\n\
|
||||||
Title: {}\n\
|
Title: {}\n\
|
||||||
Artist: {}\n\
|
Artist: {}\n\
|
||||||
Format: {}",
|
Format: {}",
|
||||||
track
|
track
|
||||||
.map(|t| t.number.to_string())
|
.map(|t| t.number.to_string())
|
||||||
.unwrap_or_else(|| "".to_string()),
|
.unwrap_or_else(|| "".to_string()),
|
||||||
@ -404,7 +419,24 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
.unwrap_or(""),
|
.unwrap_or(""),
|
||||||
));
|
));
|
||||||
|
|
||||||
TrackState { list, info }
|
TrackState {
|
||||||
|
active,
|
||||||
|
list,
|
||||||
|
state,
|
||||||
|
info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CM: CollectionManager> MhUi<CM> {
|
||||||
|
pub fn new(mut collection_manager: CM) -> Result<Self, Error> {
|
||||||
|
collection_manager.rescan_library()?;
|
||||||
|
let selection = Selection::new(Some(collection_manager.get_collection()));
|
||||||
|
Ok(MhUi {
|
||||||
|
collection_manager,
|
||||||
|
selection,
|
||||||
|
running: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(_active: bool) -> Style {
|
fn style(_active: bool) -> Style {
|
||||||
@ -465,98 +497,18 @@ impl<CM: CollectionManager> MhUi<CM> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_artist_column<B: Backend>(
|
fn render_artist_column<B: Backend>(st: ArtistState, ar: ArtistArea, fr: &mut Frame<'_, B>) {
|
||||||
artists: &[Artist],
|
Self::render_list_widget("Artists", st.list, st.state, st.active, ar.list, fr);
|
||||||
category: Category,
|
|
||||||
selection: &mut ArtistSelection,
|
|
||||||
area: ArtistArea,
|
|
||||||
frame: &mut Frame<'_, B>,
|
|
||||||
) {
|
|
||||||
let state = Self::construct_artist_state(artists);
|
|
||||||
Self::render_list_widget(
|
|
||||||
"Artists",
|
|
||||||
state.list,
|
|
||||||
&mut selection.selection,
|
|
||||||
category == Category::Artist,
|
|
||||||
area.list,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
|
|
||||||
let empty_vec: Vec<Album> = vec![];
|
|
||||||
Self::render_album_column(
|
|
||||||
if let Some(artist_index) = selection.selection.selected() {
|
|
||||||
&artists[artist_index].albums
|
|
||||||
} else {
|
|
||||||
&empty_vec
|
|
||||||
},
|
|
||||||
category,
|
|
||||||
&mut selection.album,
|
|
||||||
area.album,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_album_column<B: Backend>(
|
fn render_album_column<B: Backend>(st: AlbumState, ar: AlbumArea, fr: &mut Frame<'_, B>) {
|
||||||
albums: &[Album],
|
Self::render_list_widget("Albums", st.list, st.state, st.active, ar.list, fr);
|
||||||
category: Category,
|
Self::render_info_widget("Album info", st.info, st.active, ar.info, fr);
|
||||||
selection: &mut AlbumSelection,
|
|
||||||
area: AlbumArea,
|
|
||||||
frame: &mut Frame<'_, B>,
|
|
||||||
) {
|
|
||||||
let state = Self::construct_album_state(albums, selection.selection.selected());
|
|
||||||
Self::render_list_widget(
|
|
||||||
"Albums",
|
|
||||||
state.list,
|
|
||||||
&mut selection.selection,
|
|
||||||
category == Category::Album,
|
|
||||||
area.list,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
Self::render_info_widget(
|
|
||||||
"Album info",
|
|
||||||
state.info,
|
|
||||||
category == Category::Album,
|
|
||||||
area.info,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
|
|
||||||
let empty_vec: Vec<Track> = vec![];
|
|
||||||
Self::render_track_column(
|
|
||||||
if let Some(album_index) = selection.selection.selected() {
|
|
||||||
&albums[album_index].tracks
|
|
||||||
} else {
|
|
||||||
&empty_vec
|
|
||||||
},
|
|
||||||
category,
|
|
||||||
&mut selection.track,
|
|
||||||
area.track,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_track_column<B: Backend>(
|
fn render_track_column<B: Backend>(st: TrackState, ar: TrackArea, fr: &mut Frame<'_, B>) {
|
||||||
tracks: &[Track],
|
Self::render_list_widget("Tracks", st.list, st.state, st.active, ar.list, fr);
|
||||||
category: Category,
|
Self::render_info_widget("Track info", st.info, st.active, ar.info, fr);
|
||||||
selection: &mut TrackSelection,
|
|
||||||
area: TrackArea,
|
|
||||||
frame: &mut Frame<'_, B>,
|
|
||||||
) {
|
|
||||||
let state = Self::construct_track_state(tracks, selection.selection.selected());
|
|
||||||
Self::render_list_widget(
|
|
||||||
"Tracks",
|
|
||||||
state.list,
|
|
||||||
&mut selection.selection,
|
|
||||||
category == Category::Track,
|
|
||||||
area.list,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
Self::render_info_widget(
|
|
||||||
"Track info",
|
|
||||||
state.info,
|
|
||||||
category == Category::Track,
|
|
||||||
area.info,
|
|
||||||
frame,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,15 +553,48 @@ impl<CM: CollectionManager> Ui for MhUi<CM> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render<B: Backend>(&mut self, frame: &mut Frame<'_, B>) {
|
fn render<B: Backend>(&mut self, frame: &mut Frame<'_, B>) {
|
||||||
let areas = Self::construct_areas(frame.size());
|
let active = self.selection.active;
|
||||||
|
let areas = FrameArea::new(frame.size());
|
||||||
|
|
||||||
Self::render_artist_column(
|
let artists = self.collection_manager.get_collection();
|
||||||
self.collection_manager.get_collection(),
|
let artist_selection = &mut self.selection.artist;
|
||||||
self.selection.active,
|
let artist_state = ArtistState::new(
|
||||||
&mut self.selection.artist,
|
active == Category::Artist,
|
||||||
areas,
|
artists,
|
||||||
frame,
|
&mut artist_selection.state,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Self::render_artist_column(artist_state, areas.artist, frame);
|
||||||
|
|
||||||
|
let no_albums: Vec<Album> = vec![];
|
||||||
|
let albums = artist_selection
|
||||||
|
.state
|
||||||
|
.selected()
|
||||||
|
.map(|i| &artists[i].albums)
|
||||||
|
.unwrap_or_else(|| &no_albums);
|
||||||
|
let album_selection = &mut artist_selection.album;
|
||||||
|
let album_state = AlbumState::new(
|
||||||
|
active == Category::Album,
|
||||||
|
albums,
|
||||||
|
&mut album_selection.state,
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::render_album_column(album_state, areas.album, frame);
|
||||||
|
|
||||||
|
let no_tracks: Vec<Track> = vec![];
|
||||||
|
let tracks = album_selection
|
||||||
|
.state
|
||||||
|
.selected()
|
||||||
|
.map(|i| &albums[i].tracks)
|
||||||
|
.unwrap_or_else(|| &no_tracks);
|
||||||
|
let track_selection = &mut album_selection.track;
|
||||||
|
let track_state = TrackState::new(
|
||||||
|
active == Category::Track,
|
||||||
|
tracks,
|
||||||
|
&mut track_selection.state,
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::render_track_column(track_state, areas.track, frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user