1use crate::{Bounds, Element, LayoutId, Pixels, Result, SharedString, Style, Styled};
2use refineable::RefinementCascade;
3use std::marker::PhantomData;
4
5pub struct Svg<S> {
6 path: Option<SharedString>,
7 style: RefinementCascade<Style>,
8 state_type: PhantomData<S>,
9}
10
11pub fn svg<S>() -> Svg<S> {
12 Svg {
13 path: None,
14 style: RefinementCascade::<Style>::default(),
15 state_type: PhantomData,
16 }
17}
18
19impl<S> Svg<S> {
20 pub fn path(mut self, path: impl Into<SharedString>) -> Self {
21 self.path = Some(path.into());
22 self
23 }
24}
25
26impl<S: 'static> Element for Svg<S> {
27 type State = S;
28 type FrameState = ();
29
30 fn layout(
31 &mut self,
32 _: &mut S,
33 cx: &mut crate::ViewContext<S>,
34 ) -> anyhow::Result<(LayoutId, Self::FrameState)>
35 where
36 Self: Sized,
37 {
38 let style = self.computed_style();
39 Ok((cx.request_layout(style, [])?, ()))
40 }
41
42 fn paint(
43 &mut self,
44 bounds: Bounds<Pixels>,
45 _: &mut Self::State,
46 _: &mut Self::FrameState,
47 cx: &mut crate::ViewContext<S>,
48 ) -> Result<()>
49 where
50 Self: Sized,
51 {
52 let fill_color = self.computed_style().fill.and_then(|fill| fill.color());
53 if let Some((path, fill_color)) = self.path.as_ref().zip(fill_color) {
54 cx.paint_svg(bounds, path.clone(), fill_color)?;
55 }
56 Ok(())
57 }
58}
59
60impl<S> Styled for Svg<S> {
61 type Style = Style;
62
63 fn style_cascade(&mut self) -> &mut refineable::RefinementCascade<Self::Style> {
64 &mut self.style
65 }
66
67 fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
68 self.style.base()
69 }
70}