lumina-iced/src/ui/song_editor.rs
2025-02-22 23:38:31 -06:00

178 lines
4.7 KiB
Rust

use cosmic::{
iced::Length,
iced_widget::row,
widget::{
column, combo_box, container, dropdown, text, text_editor,
text_input, vertical_space,
},
Element, Task,
};
use tracing::debug;
use crate::core::songs::Song;
#[derive(Debug)]
pub struct SongEditor {
song: Option<Song>,
title: String,
fonts: combo_box::State<String>,
font_sizes: Vec<String>,
font: String,
font_size: usize,
verse_order: String,
lyrics: text_editor::Content,
editing: bool,
}
#[derive(Debug, Clone)]
pub enum Message {
ChangeSong(Song),
UpdateSong(Song),
ChangeFont(String),
ChangeFontSize(usize),
ChangeTitle(String),
ChangeVerseOrder(String),
ChangeLyrics(text_editor::Action),
Edit(bool),
}
impl SongEditor {
pub fn new() -> Self {
let fonts = vec![
String::from("Quicksand"),
String::from("Noto Sans"),
];
let font_sizes = vec![
"10".to_string(),
"12".to_string(),
"16".to_string(),
"18".to_string(),
"20".to_string(),
];
Self {
song: None,
fonts: combo_box::State::new(fonts),
title: String::from("Death was Arrested"),
font: String::from("Quicksand"),
font_size: 16,
font_sizes,
verse_order: String::from("Death was Arrested"),
lyrics: text_editor::Content::new(),
editing: false,
}
}
pub fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::ChangeSong(song) => {
self.song = Some(song);
Task::none()
}
Message::UpdateSong(song) => {
self.song = Some(song);
Task::none()
}
Message::ChangeFont(font) => {
self.font = font;
Task::none()
}
Message::ChangeFontSize(size) => {
if let Some(size) = self.font_sizes.get(size) {
if let Ok(size) = size.parse() {
debug!(font_size = size);
self.font_size = size;
}
}
Task::none()
}
Message::ChangeTitle(title) => {
debug!(title);
self.title = title;
Task::none()
}
Message::ChangeVerseOrder(verse_order) => {
self.verse_order = verse_order;
Task::none()
}
Message::ChangeLyrics(action) => {
self.lyrics.perform(action);
Task::none()
}
Message::Edit(edit) => {
debug!(edit);
self.editing = edit;
Task::none()
}
}
}
pub fn view(&self) -> Element<Message> {
let slide_preview =
container(vertical_space()).width(Length::FillPortion(2));
let column = column::with_children(vec![
self.toolbar(),
row![self.left_column(), slide_preview].into(),
]);
column.into()
}
fn left_column(&self) -> Element<Message> {
let title_input = text_input("song", &self.title)
.on_input(Message::ChangeTitle)
.label("Song Title");
let verse_input = text_input(
"Verse
order",
&self.verse_order,
)
.label("Verse Order")
.on_input(Message::ChangeVerseOrder);
let lyric_title = text("Lyrics");
let lyric_input = column::with_children(vec![
lyric_title.into(),
text_editor(&self.lyrics)
.on_action(Message::ChangeLyrics)
.height(Length::Fill)
.into(),
])
.spacing(5);
column::with_children(vec![
title_input.into(),
verse_input.into(),
lyric_input.into(),
])
.spacing(25)
.width(Length::FillPortion(2))
.into()
}
fn toolbar(&self) -> Element<Message> {
let selected_font = &self.font;
let selected_font_size = self
.font_sizes
.iter()
.position(|s| *s == self.font_size.to_string());
let font_selector = combo_box(
&self.fonts,
"Font",
Some(selected_font),
Message::ChangeFont,
)
.width(200);
let font_size = dropdown(
&self.font_sizes,
selected_font_size,
Message::ChangeFontSize,
);
row![font_selector, font_size].into()
}
pub fn editing(&self) -> bool {
self.editing
}
}