svg.rs

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