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