use crate::app::Message; use crate::app::Element; use iced::widget::text_input::{self, TextInput}; use iced::widget::scrollable::{self, Scrollable}; #[derive(Clone, Debug)] pub struct Lyrics { lines: Vec, scroll_state: scrollable::State, } impl Lyrics { pub fn new() -> Self { Lyrics { lines: vec![Lyric::new()], scroll_state: scrollable::State::new() } } pub fn update_line(&mut self, new_content: String, line_no: usize) { self.lines[line_no].set_content(new_content); } pub fn advance_line(&mut self, current_line: usize) { let new_line = current_line + 1; if new_line == self.lines.len() { self.lines.push(Lyric::new()) } self.lines.get_mut(new_line) .expect("Unexpected .advance_line with index beyond # of lines") .select(); self.lines.get_mut(current_line) .unwrap() .deselect(); } pub fn view(&mut self) -> Element { self.lines.iter_mut() .enumerate() .map(|(i, l)| l.view(i)) .fold(Scrollable::new(&mut self.scroll_state), |s, l| s.push(l)) .into() } } #[derive(Clone, Debug)] pub struct Lyric { state: text_input::State, value: String, } impl Lyric { pub fn new() -> Self { Lyric { state: text_input::State::new(), value: String::with_capacity(70), } } pub fn view(&mut self, line_no: usize) -> Element { TextInput::new( &mut self.state, "", &self.value, move|new_value| Message::LyricChanged { line_no, new_value }, ) .on_submit(Message::LineAdvanced(line_no)) .into() } pub fn set_content(&mut self, content: String) { self.value = content; } pub fn select(&mut self) { self.state.focus(); } pub fn deselect(&mut self) { self.state.unfocus(); } }