diff --git a/src/main.rs b/src/main.rs index 7a4cba4..522e8c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{env, path::Path}; +use std::{borrow::Cow, env, ffi::OsStr, path::Path}; use iced::{ Alignment, Color, Element, Length, Renderer, Subscription, Task, Theme, color, event, @@ -23,6 +23,8 @@ struct State { image_filter: widget::image::FilterMethod, error: Option, + info: Option, + infobar_shown: bool, } impl State { fn new() -> (Self, Task) { @@ -38,30 +40,33 @@ impl State { (state, allocate_image) } fn view(&self) -> Element<'_, Message, Theme, Renderer> { - widget::column([ - if let Some(allocation) = self.image_display.as_ref() { - widget::image::viewer(allocation.handle().clone()) - .filter_method(self.image_filter) - .max_scale(50.) - .min_scale(1.) - .width(Length::Fill) - .height(Length::Fill) - .into() - } else { - widget::container(widget::text(include_str!("usage.txt"))) - .height(Length::Fill) - .width(Length::Fill) - .align_x(Alignment::Center) - .align_y(Alignment::Center) - .into() - }, - if let Some(error) = self.error.as_ref() { - widget::text(error).style(widget::text::danger).into() - } else { - widget::space().into() - }, - ]) - .into() + let mut main = Vec::new(); + + main.push(if let Some(allocation) = self.image_display.as_ref() { + widget::image::viewer(allocation.handle().clone()) + .filter_method(self.image_filter) + .max_scale(50.) + .min_scale(1.) + .width(Length::Fill) + .height(Length::Fill) + .into() + } else { + widget::container(widget::text(include_str!("usage.txt"))) + .height(Length::Fill) + .width(Length::Fill) + .align_x(Alignment::Center) + .align_y(Alignment::Center) + .into() + }); + + if let Some(error) = self.error.as_ref() { + main.push(widget::text(error).style(widget::text::danger).into()); + } + if self.infobar_shown && self.info.is_some() { + main.push(widget::text(self.title()).into()); + } + + widget::column(main).into() } fn update(&mut self, message: Message) -> Task { match message { @@ -117,6 +122,9 @@ impl State { widget::image::FilterMethod::Nearest => widget::image::FilterMethod::Linear, } } + Key::Character("b") => { + self.infobar_shown = !self.infobar_shown; + } Key::Character("s") => { self.save_image(); @@ -146,7 +154,16 @@ impl State { } fn load_image(&mut self, path: impl AsRef) -> Result, String> { - utils::load_image(path).map(|image| { + utils::load_image(&path).map(|image| { + self.info = Some(format!( + "{} {}x{}", + path.as_ref() + .file_name() + .map(OsStr::to_string_lossy) + .unwrap_or(Cow::Borrowed("[no file]")), + image.width(), + image.height(), + )); self.image = Some(image); self.allocate_image() }) @@ -177,8 +194,11 @@ impl State { event::listen().map(Message::Event) } fn title(&self) -> String { - match self.image.as_ref() { - Some(image) => format!("imagey {}x{}", image.width(), image.height()), + match self.info.as_ref() { + Some(info) => format!( + "imagey {info} {}", + utils::string_from_filter_type(self.image_filter), + ), None => "imagey".into(), } } diff --git a/src/utils.rs b/src/utils.rs index 1477a4e..cadc05a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use iced::widget; use image::{DynamicImage, ImageDecoder, ImageReader, RgbaImage}; use rfd::FileDialog; @@ -79,3 +80,10 @@ pub fn save_image(image: Option<&RgbaImage>) -> Result<(), String> { Ok(()) } + +pub fn string_from_filter_type(f: widget::image::FilterMethod) -> &'static str { + match f { + widget::image::FilterMethod::Linear => "bilinear", + widget::image::FilterMethod::Nearest => "nearest neighbor", + } +}