diff --git a/src/app/maybe_image.rs b/src/app/maybe_image.rs new file mode 100644 index 0000000..1984854 --- /dev/null +++ b/src/app/maybe_image.rs @@ -0,0 +1,30 @@ +use iced::{task, widget}; +use image::DynamicImage; + +#[derive(Clone, Debug, Default)] +pub enum MaybeImage { + #[default] + Unloaded, + Loading(task::Handle), + Loaded(widget::image::Handle), +} +impl MaybeImage { + pub fn handle(&self) -> Option<&widget::image::Handle> { + match self { + Self::Loaded(h) => Some(&h), + _ => None, + } + } + + pub fn unload(&mut self) { + match self { + Self::Loading(task_handle) => task_handle.abort(), + _ => {} + } + *self = Self::Unloaded; + } +} + +pub fn handle_from_image(image: DynamicImage) -> widget::image::Handle { + widget::image::Handle::from_rgba(image.width(), image.height(), image.into_rgba8().into_raw()) +} diff --git a/src/app/mod.rs b/src/app/mod.rs index 427c063..f2a43f2 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -14,7 +14,9 @@ use ignore::{WalkBuilder, types::TypesBuilder}; use rayon::iter::{ParallelBridge, ParallelIterator}; use rfd::AsyncFileDialog; -use crate::SUPPORTED_TYPES; +use crate::{SUPPORTED_TYPES, app::maybe_image::MaybeImage}; + +mod maybe_image; #[derive(Clone, Debug)] enum Message { @@ -30,7 +32,7 @@ enum Message { #[derive(Default)] struct State { - images: BTreeMap>, + images: BTreeMap, columns: usize, @@ -56,12 +58,12 @@ impl State { fn update(&mut self, message: Message) -> Task { match message { Message::LoadImage(path) => { - self.images - .entry(path.clone()) - .and_modify(|e| *e = Some(widget::image::Handle::from_path(path))); + self.images.entry(path.clone()).and_modify(|e| { + *e = MaybeImage::Loaded(widget::image::Handle::from_path(path)) + }); } Message::UnloadImage(path) => { - self.images.entry(path).and_modify(|e| *e = None); + self.images.entry(path).and_modify(MaybeImage::unload); } Message::OpenImage(path) => { @@ -119,10 +121,10 @@ impl State { fn view(&self) -> Element<'_, Message, Theme, Renderer> { widget::column([ widget::scrollable( - widget::grid(self.images.iter().map(|(path, opt_handle)| { + widget::grid(self.images.iter().map(|(path, maybe_image)| { widget::button(widget::column([ widget::container( - widget::sensor(opt_handle.as_ref().map_or_else( + widget::sensor(maybe_image.handle().map_or_else( || Element::from(widget::space()), |handle| widget::image(handle).into(), )) @@ -184,7 +186,7 @@ impl State { .map(|entry| entry.into_path()) }) .filter(|path| path.is_file()) - .map(|path| (path, None)) + .map(|path| (path, MaybeImage::Unloaded)) .collect(); } }