refactor: allow the icon to be non-svg

This commit is contained in:
Ashley Wulber 2022-12-16 17:10:22 -05:00
parent c2625ef450
commit 38f7af6c07
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820

View file

@ -7,13 +7,13 @@ use iced::{
widget::{svg, Image}, widget::{svg, Image},
Length, ContentFit, Length, ContentFit,
}; };
use std::borrow::Cow; use std::{borrow::Cow, ffi::OsStr};
use std::hash::Hash; use std::hash::Hash;
use std::rc::Rc; use std::rc::Rc;
use derive_setters::Setters; use derive_setters::Setters;
use crate::{Element, Renderer}; use crate::{Element, Renderer};
/// A lazily-generated SVG icon. /// A lazily-generated icon.
#[derive(Hash, Setters)] #[derive(Hash, Setters)]
pub struct Icon<'a> { pub struct Icon<'a> {
#[setters(skip)] #[setters(skip)]
@ -30,18 +30,7 @@ pub struct Icon<'a> {
height: Option<Length>, height: Option<Length>,
} }
pub fn image_icon(name: &str, size: u16) -> Option<Image> { /// A lazily-generated icon.
freedesktop_icons::lookup(name)
.with_size(size)
.with_cache()
.find()
.map(|path| {
Image::new(path)
.width(Length::Units(size))
.height(Length::Units(size))
})
}
/// A lazily-generated SVG icon.
#[must_use] #[must_use]
pub fn icon<'a>(name: impl Into<Cow<'a, str>>, size: u16) -> Icon<'a> { pub fn icon<'a>(name: impl Into<Cow<'a, str>>, size: u16) -> Icon<'a> {
Icon { Icon {
@ -57,41 +46,59 @@ pub fn icon<'a>(name: impl Into<Cow<'a, str>>, size: u16) -> Icon<'a> {
impl<'a> Icon<'a> { impl<'a> Icon<'a> {
#[must_use] #[must_use]
fn into_svg<Message: 'static>(self) -> Element<'a, Message> { fn into_element<Message: 'static>(self) -> Element<'a, Message> {
let svg = Rc::new(self); let element = Rc::new(self);
let svg_clone = Rc::clone(&svg); let element_clone = Rc::clone(&element);
iced_lazy::lazy(svg_clone, move || -> Element<Message> { iced_lazy::lazy(element_clone, move || -> Element<Message> {
let icon = freedesktop_icons::lookup(&svg.name) let icon = freedesktop_icons::lookup(&element.name)
.with_size(svg.size) .with_size(element.size)
.with_theme(&svg.theme) .with_theme(&element.theme)
.with_cache() .with_cache()
.force_svg()
.find(); .find();
let icon = if icon.is_none() {
let handle = if let Some(path) = icon { freedesktop_icons::lookup(&element.name)
svg::Handle::from_path(path) .with_size(element.size)
.with_cache()
.find()
} else { } else {
eprintln!("icon '{}' size {} not found", svg.name, svg.size); icon
svg::Handle::from_memory(Vec::new())
}; };
let mut widget = svg::Svg::<Renderer>::new(handle) if icon.as_ref().map(|path| path.extension() == Some(&OsStr::new("svg"))).unwrap_or(true) {
.style(svg.style) let handle = if let Some(path) = icon {
.width(svg.width.unwrap_or(Length::Units(svg.size))) svg::Handle::from_path(path)
.height(svg.height.unwrap_or(Length::Units(svg.size))); } else {
eprintln!("icon '{}' size {} not found", element.name, element.size);
svg::Handle::from_memory(Vec::new())
};
if let Some(content_fit) = svg.content_fit { let mut widget = svg::Svg::<Renderer>::new(handle)
widget = widget.content_fit(content_fit); .style(element.style)
.width(element.width.unwrap_or(Length::Units(element.size)))
.height(element.height.unwrap_or(Length::Units(element.size)));
if let Some(content_fit) = element.content_fit {
widget = widget.content_fit(content_fit);
}
widget.into()
} else {
let icon_path = icon.unwrap();
let mut image = Image::new(icon_path)
.width(element.width.unwrap_or(Length::Units(element.size)))
.height(element.height.unwrap_or(Length::Units(element.size)));
if let Some(content_fit) = element.content_fit {
image = image.content_fit(content_fit);
}
image.into()
} }
widget.into()
}).into() }).into()
} }
} }
impl<'a, Message: 'static> From<Icon<'a>> for Element<'a, Message> { impl<'a, Message: 'static> From<Icon<'a>> for Element<'a, Message> {
fn from(icon: Icon<'a>) -> Self { fn from(icon: Icon<'a>) -> Self {
icon.into_svg::<Message>() icon.into_element::<Message>()
} }
} }