use crate::app::Theme; use crate::app::Message; use crate::app::Element; use iced::Align; use iced::Length; 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 { let mut lyric = Lyric::new(); lyric.select(); Lyrics { lines: vec![lyric], 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, theme: Theme) -> Element { let is_sole_line = self.lines.len() == 1; self.lines.iter_mut() .enumerate() .map(|(i, l)| l.view(is_sole_line, i, theme)) .fold(Scrollable::new(&mut self.scroll_state), |s, l| s.push(l)) .width(Length::Fill) .align_items(Align::Center) .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, show_placeholder: bool, line_no: usize, theme: Theme) -> Element { let placeholder = if show_placeholder { "Paste some lyrics to get started" } else if self.state.is_focused() { "..." } else { "" }; let size = if self.state.is_focused() { 30 } else { 20 }; TextInput::new( &mut self.state, placeholder, &self.value, move|new_value| Message::LyricChanged { line_no, new_value }, ) .style(theme) .size(size) .width(Length::Units(300)) .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(); self.state.move_cursor_to_end(); } pub fn deselect(&mut self) { self.state.unfocus(); } }