deLyrium/src/app.rs

176 lines
4.2 KiB
Rust
Raw Normal View History

2022-01-08 02:07:11 +00:00
use crate::lyrics::LyricEvent;
2022-01-03 23:19:10 +00:00
use crate::controls::ControlsEvent;
2022-01-01 17:28:23 +00:00
use crate::load_song::load_song;
2022-01-02 04:11:47 +00:00
use crate::editor::Editor;
2022-01-01 16:20:25 +00:00
use crate::file_select::FileSelector;
use rfd::AsyncFileDialog;
2022-01-01 06:02:54 +00:00
use std::path::PathBuf;
2022-01-01 04:41:12 +00:00
use core::time::Duration;
2021-12-31 20:32:23 +00:00
use iced::Subscription;
use iced::Clipboard;
use iced::Command;
use iced::Application;
2021-12-30 22:32:52 +00:00
use iced::Element;
2021-12-31 20:32:23 +00:00
use iced::executor;
2022-01-01 04:41:12 +00:00
use iced_futures::time;
2021-12-31 20:32:23 +00:00
use iced_native::subscription;
use iced_native::keyboard;
2022-01-01 06:02:54 +00:00
use iced_native::window;
2021-12-31 20:32:23 +00:00
use iced_native::event::Event;
2021-12-30 22:32:52 +00:00
pub struct DelyriumApp {
2022-01-02 04:11:47 +00:00
lyrics_component: Option<Editor>,
2022-01-01 16:20:25 +00:00
file_selector: FileSelector,
2022-01-02 03:08:00 +00:00
size: (u32, u32),
2022-01-01 04:41:12 +00:00
}
2021-12-30 22:32:52 +00:00
#[derive(Clone, Debug)]
pub enum Message {
2022-01-08 02:07:11 +00:00
LyricEvent {
2021-12-30 22:32:52 +00:00
line_no: usize,
2022-01-08 02:07:11 +00:00
kind: LyricEvent,
2021-12-30 22:32:52 +00:00
},
2021-12-31 20:32:23 +00:00
PasteSent,
2022-01-01 04:41:12 +00:00
Tick,
2022-01-01 06:02:54 +00:00
PromptForFile,
FileOpened(PathBuf),
2022-01-02 03:08:00 +00:00
Resized(u32, u32),
2022-01-03 23:19:10 +00:00
ControlsEvent(ControlsEvent),
2022-01-01 06:02:54 +00:00
Null,
2021-12-30 22:32:52 +00:00
}
2021-12-31 20:32:23 +00:00
impl Application for DelyriumApp {
2021-12-30 22:32:52 +00:00
type Message = Message;
2021-12-31 20:32:23 +00:00
type Executor = executor::Default;
type Flags = ();
2021-12-30 22:32:52 +00:00
2021-12-31 20:32:23 +00:00
fn new(_: Self::Flags) -> (Self, Command<Message>) {
(
DelyriumApp {
lyrics_component: None,
2022-01-01 04:41:12 +00:00
file_selector: FileSelector::default(),
2022-01-02 03:08:00 +00:00
size: (0, 0),
2021-12-31 20:32:23 +00:00
},
Command::none(),
)
2021-12-30 22:32:52 +00:00
}
fn title(&self) -> String {
String::from("Delyrium")
}
2021-12-31 20:32:23 +00:00
fn update(&mut self, message: Message, clipboard: &mut Clipboard) -> Command<Message>{
2022-01-01 06:02:54 +00:00
let mut command = None;
match message {
2022-01-08 02:07:11 +00:00
Message::LyricEvent { line_no, kind } => {
if let Some(lyrics) = self.lyrics_component.as_mut() {
2022-01-08 02:07:11 +00:00
lyrics.handle_lyric_event(line_no, kind);
}
2021-12-31 20:32:23 +00:00
},
Message::PasteSent => {
if let Some(lyrics) = self.lyrics_component.as_mut() {
2022-01-08 15:28:42 +00:00
#[allow(clippy::or_fun_call)] // This is a const
let clip_text = clipboard.read().unwrap_or(String::new());
let clip_pasted_len = clip_text.chars()
.filter(|c| *c != '\r' && *c != '\n')
.count();
let line = lyrics.current_line_mut().1;
line.value.truncate(line.value.len() - clip_pasted_len);
lyrics.insert_text(clip_text);
}
2022-01-01 04:41:12 +00:00
},
Message::Tick => {
if self.lyrics_component.is_none() {
self.file_selector.tick();
2022-01-01 04:41:12 +00:00
}
2022-01-01 06:02:54 +00:00
},
Message::FileOpened(path) => {
println!("File opened! {}", path.display());
let song = load_song(&path).unwrap().format;
let (editor, cmd) = Editor::new(song, self.size);
self.lyrics_component = Some(editor);
command = Some(cmd);
2022-01-01 06:02:54 +00:00
},
Message::PromptForFile => {
let task = async {
let handle = AsyncFileDialog::new()
2022-01-01 17:28:23 +00:00
.add_filter("Song Files", &["mp3", "flac", "ogg", "opus", "wav", "mkv"])
2022-01-01 06:02:54 +00:00
.set_title("Select a song")
.pick_file()
.await;
if let Some(h) = handle {
Message::FileOpened(h.path().to_owned())
} else {
Message::Null
}
};
command = Some(task.into());
},
2022-01-02 03:08:00 +00:00
Message::Resized(w, h) => {
self.size = (w, h);
if let Some(lyrics) = self.lyrics_component.as_mut() {
lyrics.notify_resized(w, h);
}
2022-01-03 23:19:10 +00:00
},
Message::ControlsEvent(e) => {
if let Some(lyrics) = self.lyrics_component.as_mut() {
lyrics.handle_controls_event(e);
}
},
2022-01-01 06:02:54 +00:00
Message::Null => { },
}
2022-01-01 06:02:54 +00:00
command.unwrap_or_else(Command::none)
2021-12-30 22:32:52 +00:00
}
fn view(&mut self) -> Element<Message> {
if let Some(lyrics) = self.lyrics_component.as_mut() {
lyrics.view()
} else {
self.file_selector.view()
2022-01-01 04:41:12 +00:00
}
2021-12-30 22:32:52 +00:00
}
2021-12-31 20:32:23 +00:00
fn subscription(&self) -> Subscription<Message> {
2022-01-01 04:41:12 +00:00
let runtime_events = subscription::events_with(|event, _| {
2021-12-31 20:32:23 +00:00
match event {
Event::Keyboard(keyboard::Event::KeyPressed {key_code, modifiers}) => {
match (key_code, modifiers) {
(
keyboard::KeyCode::V,
keyboard::Modifiers { control, .. }
2022-01-08 15:28:42 +00:00
) if control => {
2021-12-31 20:32:23 +00:00
Some(Message::PasteSent)
}
_ => { None }
}
2022-01-01 06:02:54 +00:00
},
Event::Window(window::Event::FileDropped(path)) => {
Some(Message::FileOpened(path))
},
2022-01-02 03:08:00 +00:00
Event::Window(window::Event::Resized{width,height}) => {
Some(Message::Resized(width,height))
},
2021-12-31 20:32:23 +00:00
_ => { None }
}
2022-01-01 04:41:12 +00:00
});
2022-01-03 23:19:10 +00:00
let is_animating = if let Some(editor) = &self.lyrics_component {
editor.is_animating()
} else {
true
};
2022-01-01 04:41:12 +00:00
2022-01-03 23:19:10 +00:00
let fps30 = if is_animating {
time::every(Duration::from_millis(1000 / 30)).map(|_| Message::Tick)
} else {
2022-01-03 23:19:10 +00:00
Subscription::none()
};
Subscription::batch([
runtime_events,
fps30
])
2021-12-31 20:32:23 +00:00
}
2021-12-30 22:32:52 +00:00
}