svg.rs

 1use crate::{
 2    Bounds, Element, ElementContext, Hitbox, InteractiveElement, Interactivity, IntoElement,
 3    LayoutId, Pixels, SharedString, StyleRefinement, Styled,
 4};
 5use util::ResultExt;
 6
 7/// An SVG element.
 8pub struct Svg {
 9    interactivity: Interactivity,
10    path: Option<SharedString>,
11}
12
13/// Create a new SVG element.
14pub fn svg() -> Svg {
15    Svg {
16        interactivity: Interactivity::default(),
17        path: None,
18    }
19}
20
21impl Svg {
22    /// Set the path to the SVG file for this element.
23    pub fn path(mut self, path: impl Into<SharedString>) -> Self {
24        self.path = Some(path.into());
25        self
26    }
27}
28
29impl Element for Svg {
30    type BeforeLayout = ();
31    type AfterLayout = Option<Hitbox>;
32
33    fn before_layout(&mut self, cx: &mut ElementContext) -> (LayoutId, Self::BeforeLayout) {
34        let layout_id = self
35            .interactivity
36            .before_layout(cx, |style, cx| cx.request_layout(&style, None));
37        (layout_id, ())
38    }
39
40    fn after_layout(
41        &mut self,
42        bounds: Bounds<Pixels>,
43        _before_layout: &mut Self::BeforeLayout,
44        cx: &mut ElementContext,
45    ) -> Option<Hitbox> {
46        self.interactivity
47            .after_layout(bounds, bounds.size, cx, |_, _, hitbox, _| hitbox)
48    }
49
50    fn paint(
51        &mut self,
52        bounds: Bounds<Pixels>,
53        _before_layout: &mut Self::BeforeLayout,
54        hitbox: &mut Option<Hitbox>,
55        cx: &mut ElementContext,
56    ) where
57        Self: Sized,
58    {
59        self.interactivity
60            .paint(bounds, hitbox.as_ref(), cx, |style, cx| {
61                if let Some((path, color)) = self.path.as_ref().zip(style.text.color) {
62                    cx.paint_svg(bounds, path.clone(), color).log_err();
63                }
64            })
65    }
66}
67
68impl IntoElement for Svg {
69    type Element = Self;
70
71    fn into_element(self) -> Self::Element {
72        self
73    }
74}
75
76impl Styled for Svg {
77    fn style(&mut self) -> &mut StyleRefinement {
78        &mut self.interactivity.base_style
79    }
80}
81
82impl InteractiveElement for Svg {
83    fn interactivity(&mut self) -> &mut Interactivity {
84        &mut self.interactivity
85    }
86}