use crate::{IconError, IconName, Weight};
use gpui::{App, Hsla, IntoElement, Pixels, RenderOnce, SharedString, Styled, Window, px, svg};
#[derive(IntoElement, Clone, Debug)]
pub struct Icon {
name: IconName,
weight: Weight,
size: Pixels,
color: Option<Hsla>,
}
impl Icon {
#[must_use]
pub fn new(name: IconName) -> Self {
Self {
name,
weight: Weight::default_enabled(),
size: px(16.0),
color: None,
}
}
pub fn try_new(name: IconName, weight: Weight) -> Result<Self, IconError> {
name.path(weight)?;
Ok(Self {
name,
weight,
size: px(16.0),
color: None,
})
}
#[must_use]
pub const fn name(&self) -> IconName {
self.name
}
#[must_use]
pub const fn icon_weight(&self) -> Weight {
self.weight
}
#[must_use]
pub fn weight(mut self, weight: Weight) -> Self {
self.weight = weight;
self
}
pub fn try_with_weight(mut self, weight: Weight) -> Result<Self, IconError> {
self.name.path(weight)?;
self.weight = weight;
Ok(self)
}
#[must_use]
pub fn size(mut self, size: impl Into<Pixels>) -> Self {
self.size = size.into();
self
}
#[must_use]
pub fn with_size(self, size: impl Into<Pixels>) -> Self {
self.size(size)
}
#[must_use]
pub const fn icon_size(&self) -> Pixels {
self.size
}
#[must_use]
pub fn color(mut self, color: impl Into<Hsla>) -> Self {
self.color = Some(color.into());
self
}
#[must_use]
pub fn text_color(self, color: impl Into<Hsla>) -> Self {
self.color(color)
}
#[must_use]
pub const fn icon_color(&self) -> Option<Hsla> {
self.color
}
pub fn path(&self) -> Result<SharedString, IconError> {
self.name.path(self.weight)
}
}
impl RenderOnce for Icon {
fn render(self, window: &mut Window, _cx: &mut App) -> impl IntoElement {
let path = self.path().unwrap_or_else(|_| {
format!(
"phosphor/{}/{}.svg",
self.weight.as_str(),
self.name.as_str()
)
.into()
});
svg()
.flex_none()
.size(self.size)
.text_color(self.color.unwrap_or(window.text_style().color))
.path(path)
}
}