deLyrium/src/editor.rs

133 lines
3.1 KiB
Rust

use crate::lyrics::LyricEvent;
use iced::Command;
use iced::Image;
use iced::image::Handle;
use image::DynamicImage;
use crate::controls::ControlsEvent;
use crate::controls::Controls;
use crate::lyrics::Lyric;
use crate::lyrics::Lyrics;
use crate::app::Message;
use iced::Element;
use crate::styles::Theme;
use iced::Container;
use iced::Row;
use crate::palette::Palette;
use crate::load_song::extract_cover;
use iced::Length;
use image::imageops::FilterType;
use symphonia::core::formats::FormatReader;
use image::GenericImageView;
pub struct Editor {
lyrics: Lyrics,
theme: Theme,
controls: Controls,
bg_img: DynamicImage,
cached_resized_bg: Option<Handle>,
dimensions: (u32, u32),
}
impl Editor {
pub fn new(mut song: Box<dyn FormatReader>, size: (u32, u32)) -> (Self, Command<Message>) {
let cover = extract_cover(song.as_mut());
let theme = cover.as_ref()
.map(|cover| {
Theme::from_palette(
Palette::generate(cover)
)
}).unwrap_or_else(Theme::default);
let cover = cover.expect("TODO");
#[cfg(not(debug_assertions))]
let cover = cover.blur((cover.width() / 100) as f32);
let bg_img = DynamicImage::ImageBgra8(cover.into_bgra8());
let (controls, cmd) = Controls::new(song);
(Self {
lyrics: Lyrics::new(),
dimensions: size,
cached_resized_bg: None,
controls, theme, bg_img,
}, cmd)
}
// TODO: work on untangling this mess
pub fn handle_controls_event(&mut self, event: ControlsEvent) {
self.controls.handle_event(event)
}
pub fn insert_text(&mut self, text: String) {
self.lyrics.insert_text(text);
}
pub fn handle_lyric_event(&mut self, line_no: usize, kind: LyricEvent) {
self.lyrics.handle_event(line_no, kind)
}
pub fn current_line_mut(&mut self) -> (usize, &mut Lyric) {
self.lyrics.current_line_mut()
}
pub fn is_animating(&self) -> bool {
self.controls.is_playing()
}
fn calculate_margin_width(&self) -> u32 {
let (w, _h) = self.dimensions;
let body_size = (w / 5).max(550);
w.saturating_sub(body_size) / 2
}
pub fn notify_resized(&mut self, w: u32, h: u32) {
self.dimensions = (w, h);
let (_w, h) = self.dimensions;
let margin_w = self.calculate_margin_width();
self.cached_resized_bg = if margin_w != 0 {
let resized_bg = self.bg_img.resize_to_fill(margin_w, h, FilterType::Nearest);
Some(Handle::from_pixels(
resized_bg.width(),
resized_bg.height(),
resized_bg.into_bgra8().into_raw()
))
} else { None };
}
pub fn view(&mut self) -> Element<Message> {
let row = if let Some(margin_bg) = &self.cached_resized_bg {
let (w, _h) = self.dimensions;
let (img1, img2) = (
Image::new(margin_bg.clone())
.width(Length::Units(w as u16))
.height(Length::Fill),
Image::new(margin_bg.clone())
.width(Length::Units(w as u16))
.height(Length::Fill),
);
Row::new()
.push(img1)
.push(self.controls.view_progress(self.theme))
.push(self.lyrics.view(self.theme))
.push(img2)
} else {
Row::new()
.push(self.controls.view_progress(self.theme))
.push(self.lyrics.view(self.theme))
};
Container::new(row)
.style(self.theme)
.height(Length::Fill)
.into()
}
}