1use crate::{IconError, IconName, Weight};
2use gpui::{App, Hsla, IntoElement, Pixels, RenderOnce, SharedString, Styled, Window, px, svg};
3
4#[derive(IntoElement, Clone, Debug)]
11pub struct Icon {
12 name: IconName,
13 weight: Weight,
14 size: Pixels,
15 color: Option<Hsla>,
16}
17
18impl Icon {
19 #[must_use]
21 pub fn new(name: IconName) -> Self {
22 Self {
23 name,
24 weight: Weight::default_enabled(),
25 size: px(16.0),
26 color: None,
27 }
28 }
29
30 pub fn try_new(name: IconName, weight: Weight) -> Result<Self, IconError> {
32 name.path(weight)?;
33 Ok(Self {
34 name,
35 weight,
36 size: px(16.0),
37 color: None,
38 })
39 }
40
41 #[must_use]
43 pub const fn name(&self) -> IconName {
44 self.name
45 }
46
47 #[must_use]
49 pub const fn icon_weight(&self) -> Weight {
50 self.weight
51 }
52
53 #[must_use]
58 pub fn weight(mut self, weight: Weight) -> Self {
59 self.weight = weight;
60 self
61 }
62
63 pub fn try_with_weight(mut self, weight: Weight) -> Result<Self, IconError> {
65 self.name.path(weight)?;
66 self.weight = weight;
67 Ok(self)
68 }
69
70 #[must_use]
72 pub fn size(mut self, size: impl Into<Pixels>) -> Self {
73 self.size = size.into();
74 self
75 }
76
77 #[must_use]
79 pub fn with_size(self, size: impl Into<Pixels>) -> Self {
80 self.size(size)
81 }
82
83 #[must_use]
85 pub const fn icon_size(&self) -> Pixels {
86 self.size
87 }
88
89 #[must_use]
91 pub fn color(mut self, color: impl Into<Hsla>) -> Self {
92 self.color = Some(color.into());
93 self
94 }
95
96 #[must_use]
98 pub fn text_color(self, color: impl Into<Hsla>) -> Self {
99 self.color(color)
100 }
101
102 #[must_use]
104 pub const fn icon_color(&self) -> Option<Hsla> {
105 self.color
106 }
107
108 pub fn path(&self) -> Result<SharedString, IconError> {
110 self.name.path(self.weight)
111 }
112}
113
114impl RenderOnce for Icon {
115 fn render(self, window: &mut Window, _cx: &mut App) -> impl IntoElement {
116 let path = self.path().unwrap_or_else(|_| {
117 format!(
120 "phosphor/{}/{}.svg",
121 self.weight.as_str(),
122 self.name.as_str()
123 )
124 .into()
125 });
126 svg()
127 .flex_none()
128 .size(self.size)
129 .text_color(self.color.unwrap_or(window.text_style().color))
130 .path(path)
131 }
132}