1use crate::{
2 self as gpui2, scene,
3 style::{Style, StyleHelpers, Styleable},
4 Element, IntoElement, Layout, LayoutId, Rgba,
5};
6use refineable::RefinementCascade;
7use std::borrow::Cow;
8use util::ResultExt;
9
10#[derive(IntoElement)]
11pub struct Svg {
12 path: Option<Cow<'static, str>>,
13 style: RefinementCascade<Style>,
14}
15
16pub fn svg() -> Svg {
17 Svg {
18 path: None,
19 style: RefinementCascade::<Style>::default(),
20 }
21}
22
23impl Svg {
24 pub fn path(mut self, path: impl Into<Cow<'static, str>>) -> Self {
25 self.path = Some(path.into());
26 self
27 }
28}
29
30impl<V: 'static> Element<V> for Svg {
31 type PaintState = ();
32
33 fn layout(
34 &mut self,
35 _: &mut V,
36 cx: &mut crate::LayoutContext<V>,
37 ) -> anyhow::Result<(LayoutId, Self::PaintState)>
38 where
39 Self: Sized,
40 {
41 let style = self.computed_style();
42 Ok((cx.add_layout_node(style, [])?, ()))
43 }
44
45 fn paint(
46 &mut self,
47 _: &mut V,
48 layout: &Layout,
49 _: &mut Self::PaintState,
50 cx: &mut crate::paint_context::PaintContext<V>,
51 ) where
52 Self: Sized,
53 {
54 let fill_color = self.computed_style().fill.and_then(|fill| fill.color());
55 if let Some((path, fill_color)) = self.path.as_ref().zip(fill_color) {
56 if let Some(svg_tree) = cx.asset_cache.svg(path).log_err() {
57 let icon = scene::Icon {
58 bounds: layout.bounds,
59 svg: svg_tree,
60 path: path.clone(),
61 color: Rgba::from(fill_color).into(),
62 };
63
64 cx.scene.push_icon(icon);
65 }
66 }
67 }
68}
69
70impl Styleable for Svg {
71 type Style = Style;
72
73 fn style_cascade(&mut self) -> &mut refineable::RefinementCascade<Self::Style> {
74 &mut self.style
75 }
76
77 fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
78 self.style.base()
79 }
80}
81
82impl StyleHelpers for Svg {}