Reputation: 353
i have this rust tui which pass a list of song title's into a tui.rs crate to show the list in terminal user interface. here which i do is recursively checking the available .mp3
files and adding the files metadata to a struct which is SongStruct
so when i need to show the titles of of the songs i had to iter the vec of SongStruct
and add the SongStruct.title
to a vec and add to ListItem
in tui.rs. if the user click the selected item it only selected the give string which is SongStruct.title
so rather than passing a string of text i need to pass the whole struct and show the selected SongStruct.title
. is there any way to pass the whole struct and show the title and when user select an item get the struct details and call a function. here a below my tui code and struct
pub struct SongStruct {
pub title: String,
pub artist: String,
pub file_path: String,
}
use std::{
io,
thread,
time::Duration
};
use tui::{
backend::CrosstermBackend,
Terminal,
widgets::{Widget,Block,Borders,List,ListItem},
layout::{Layout,Direction,Constraint,Alignment},
style::{Style,Color,Modifier}
};
use crossterm::{
terminal::{enable_raw_mode,disable_raw_mode,EnterAlternateScreen,LeaveAlternateScreen},
execute
};
use tui::text::{Span, Spans};
use crate::audio::Song::SongStruct;
pub fn ui(songList: Vec<SongStruct>)->Result<(),io::Error>{
enable_raw_mode().expect("couldn't enable raw mode");
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
terminal.draw(|rect|{
let size = rect.size();
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints(
[
Constraint::Percentage(30),
Constraint::Percentage(70)
].as_ref()
)
.split(rect.size());
let block = Block::default().title("rust-play").borders(Borders::ALL);
let items = [ListItem::new("Item 1"), ListItem::new("Item 2"), ListItem::new("Item 3")];
let song_list:Vec<String> = songList.into_iter().map(|song|song.title).collect();
let listsongs:Vec<_> = song_list.into_iter().map(ListItem::new).collect();
let title_span = Span::styled("Title Text", Style::default().fg(Color::Red));
let list =List::new(listsongs)
.block(Block::default().title(title_span).title_alignment(Alignment::Center).borders(Borders::ALL))
.style(Style::default().fg(Color::Yellow))
.highlight_style(Style::default().add_modifier(Modifier::ITALIC))
.highlight_symbol(">>");
rect.render_widget(block,chunks[0]);
rect.render_widget(list,chunks[1]);
})?;
thread::sleep(Duration::from_millis(5000));
disable_raw_mode()?;
Ok(())
}`
Upvotes: 0
Views: 221
Reputation: 197
The answer is no.
If you look into the source, you can see that what it stores is just the string (Actually Text
and Style
), and it is impossible to pass anything else, including your own struct into ItemList
.
Assuming you don't want to write your own struct, a simple workaround would be to keep a separate copy of Vec<SongStruct>
that is passed into ui()
as a reference.
Hope this helps.
Upvotes: 0