diff --git a/src/main.rs b/src/main.rs index f965f8f..d83ac71 100755 --- a/src/main.rs +++ b/src/main.rs @@ -54,6 +54,7 @@ use crate::core::file; use crate::core::kinds::ServiceItemKind; use crate::core::model::KindWrapper; use crate::ui::image_editor::{self, ImageEditor}; +use crate::ui::image_loader::load_images; use crate::ui::presentation_editor::{self, PresentationEditor}; use crate::ui::text_svg::{self}; use crate::ui::video_editor::{self, VideoEditor}; @@ -1397,16 +1398,25 @@ impl cosmic::Application for App { item = presentation.to_service_item(); } } + if matches!(kind, core::model::LibraryKind::Song) { + item.slides = item + .slides + .into_par_iter() + .map(|slide| { + let fontdb = Arc::clone(&self.fontdb); + text_svg::text_svg_generator( + slide.clone(), + &fontdb, + ) + .unwrap_or(slide) + }) + .collect(); + } item.slides = item .slides .into_par_iter() .map(|slide| { - let fontdb = Arc::clone(&self.fontdb); - text_svg::text_svg_generator( - slide.clone(), - &fontdb, - ) - .unwrap_or(slide) + load_images(slide.clone()).unwrap_or(slide) }) .collect(); self.update(Message::AddServiceItem(index, item)) @@ -1441,18 +1451,28 @@ impl cosmic::Application for App { Task::none() } Message::AppendServiceItem(mut item) => { + if matches!(item.kind, ServiceItemKind::Song(_)) { + item.slides = item + .slides + .into_par_iter() + .map(|slide| { + let fontdb = Arc::clone(&self.fontdb); + text_svg::text_svg_generator( + slide.clone(), + &fontdb, + ) + .unwrap_or(slide) + }) + .collect(); + } item.slides = item .slides .into_par_iter() .map(|slide| { - let fontdb = Arc::clone(&self.fontdb); - text_svg::text_svg_generator( - slide.clone(), - &fontdb, - ) - .unwrap_or(slide) + load_images(slide.clone()).unwrap_or(slide) }) .collect(); + Arc::make_mut(&mut self.service).push(item); self.presenter.update_items(self.service.clone()); Task::none() diff --git a/src/ui/image_loader.rs b/src/ui/image_loader.rs new file mode 100644 index 0000000..596fbe5 --- /dev/null +++ b/src/ui/image_loader.rs @@ -0,0 +1,32 @@ +use std::io; + +use cosmic::widget::image::Handle; + +use crate::core::slide::{BackgroundKind, Slide}; + +type Result = std::result::Result; + +pub fn load_images(mut slide: Slide) -> Result { + if matches!(slide.background().kind, BackgroundKind::Image) { + let path = &slide.background().path; + let image = + image::open(path).map_err(|e| Error::ImageError(e))?; + let (width, height, pixels) = ( + image.width(), + image.height(), + image.to_rgba8().to_vec(), + ); + + slide.background.image_handle = + Some(Handle::from_rgba(width, height, pixels)); + Ok(slide) + } else { + Ok(slide) + } +} + +pub enum Error { + NonImage, + LoadingError(io::Error), + ImageError(image::ImageError), +} diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 7f7ab1e..a08128f 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -7,6 +7,7 @@ pub mod presentation_editor; pub mod presenter; // pub mod service; pub mod gst_video; +pub mod image_loader; pub mod slide_editor; pub mod song_editor; pub mod text_svg; diff --git a/src/ui/presenter.rs b/src/ui/presenter.rs index 96da10b..32bb0c6 100644 --- a/src/ui/presenter.rs +++ b/src/ui/presenter.rs @@ -40,7 +40,7 @@ use crate::core::slide::Slide; use crate::core::slide_actions::{self, ObsAction}; use crate::ui::gst_video; use crate::ui::library::elide_text; -use crate::ui::widgets::loaded_image::loaded_image; +// use crate::ui::widgets::loaded_image::loaded_image; // const REFERENCE_WIDTH: f32 = 1920.0; static DEFAULT_SLIDE: LazyLock = LazyLock::new(Slide::default); @@ -323,7 +323,7 @@ impl Presenter { .update(Message::SlideChange(slide.clone())); } } - Message::SlideChange(mut slide) => { + Message::SlideChange(slide) => { let slide_text = slide.text(); debug!(slide_text, "slide changed"); let bg = slide.background().clone(); @@ -333,25 +333,25 @@ impl Presenter { == slide.background(); // self.current_slide_index = slide; - if matches!( - slide.background().kind, - BackgroundKind::Image - ) { - if let Ok((width, height, pixels)) = image::open( - &slide.background().path, - ) - .map(|image| { - ( - image.width(), - image.height(), - image.to_rgba8().to_vec(), - ) - }) { - let handle = - Handle::from_rgba(width, height, pixels); - slide.background.image_handle = Some(handle); - }; - } + // if matches!( + // slide.background().kind, + // BackgroundKind::Image + // ) { + // if let Ok((width, height, pixels)) = image::open( + // &slide.background().path, + // ) + // .map(|image| { + // ( + // image.width(), + // image.height(), + // image.to_rgba8().to_vec(), + // ) + // }) { + // let handle = + // Handle::from_rgba(width, height, pixels); + // slide.background.image_handle = Some(handle); + // }; + // } debug!("cloning slide..."); self.current_slide = slide.clone(); @@ -1204,14 +1204,29 @@ pub(crate) fn slide_view<'a>( match slide.background().kind { BackgroundKind::Image => { stack = stack.push( - Container::new( - loaded_image(slide.background().path.into()) - .content_fit(ContentFit::Contain) - .width(width) - .height(Length::Fill), - ) - .center(Length::Fill) - .clip(true), + if let Some(handle) = + slide.background().image_handle.as_ref() + { + debug!("I am rendering a handle"); + Container::new( + cosmic_image(handle) + .content_fit(ContentFit::Contain) + .width(width) + .height(Length::Fill), + ) + .center(Length::Fill) + .clip(true) + } else { + debug!("Am a punk!"); + Container::new( + cosmic_image(&slide.background().path) + .content_fit(ContentFit::Contain) + .width(width) + .height(Length::Fill), + ) + .center(Length::Fill) + .clip(true) + }, ); } BackgroundKind::Video => { diff --git a/src/ui/widgets/loaded_image.rs b/src/ui/widgets/loaded_image.rs index 81a7730..cac3f28 100644 --- a/src/ui/widgets/loaded_image.rs +++ b/src/ui/widgets/loaded_image.rs @@ -8,15 +8,18 @@ use iced_core::{ Widget, layout, mouse, overlay, renderer, }; -pub fn loaded_image<'a, Message: 'static, Theme>( +pub fn loaded_image<'a, Message: 'static, Theme, Renderer>( handle: ::Handle, + content: cosmic::iced::Element<'a, Message, Theme, Renderer>, ) -> LoadedImage<'a, Message, Theme, cosmic::Renderer> where Theme: iced_widget::container::Catalog, ::Class<'a>: From>, + Renderer: iced_core::Renderer + iced_core::image::Renderer, + ::Handle: 'a, { - LoadedImage::new(handle) + LoadedImage::new(handle, content) } /// Forces the wrapped image to be loaded before drawing. @@ -42,10 +45,13 @@ where /// Creates an empty [`LoadedImage`]. pub(crate) fn new( handle: ::Handle, + content: impl Into< + cosmic::iced::Element<'a, Message, Theme, Renderer>, + >, ) -> Self { LoadedImage { handle: handle.clone(), - content: cosmic::widget::Image::new(handle).into(), + content: content.into(), } } } diff --git a/src/ui/widgets/mod.rs b/src/ui/widgets/mod.rs index 96775ba..cf5b05e 100644 --- a/src/ui/widgets/mod.rs +++ b/src/ui/widgets/mod.rs @@ -2,6 +2,6 @@ #[allow(clippy::nursery)] #[allow(clippy::pedantic)] pub mod draggable; -pub mod loaded_image; +// pub mod loaded_image; pub mod verse_editor; // pub mod slide_text;