1use crate::{
2 Bounds, Element, ElementContext, ElementId, InteractiveElement, InteractiveElementState,
3 Interactivity, IntoElement, 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 State = InteractiveElementState;
31
32 fn request_layout(
33 &mut self,
34 element_state: Option<Self::State>,
35 cx: &mut ElementContext,
36 ) -> (LayoutId, Self::State) {
37 self.interactivity.layout(element_state, cx, |style, cx| {
38 cx.request_layout(&style, None)
39 })
40 }
41
42 fn paint(
43 &mut self,
44 bounds: Bounds<Pixels>,
45 element_state: &mut Self::State,
46 cx: &mut ElementContext,
47 ) where
48 Self: Sized,
49 {
50 self.interactivity
51 .paint(bounds, bounds.size, element_state, cx, |style, _, cx| {
52 if let Some((path, color)) = self.path.as_ref().zip(style.text.color) {
53 cx.paint_svg(bounds, path.clone(), color).log_err();
54 }
55 })
56 }
57}
58
59impl IntoElement for Svg {
60 type Element = Self;
61
62 fn element_id(&self) -> Option<ElementId> {
63 self.interactivity.element_id.clone()
64 }
65
66 fn into_element(self) -> Self::Element {
67 self
68 }
69}
70
71impl Styled for Svg {
72 fn style(&mut self) -> &mut StyleRefinement {
73 &mut self.interactivity.base_style
74 }
75}
76
77impl InteractiveElement for Svg {
78 fn interactivity(&mut self) -> &mut Interactivity {
79 &mut self.interactivity
80 }
81}