1use crate::{
2 div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementId,
3 ElementIdentity, EventListeners, Hover, Identified, Interactive, IntoAnyElement, LayoutId,
4 NonFocusable, Pixels, SharedString, StyleRefinement, Styled,
5};
6use util::ResultExt;
7
8pub struct Svg<V: 'static + Send + Sync, K: ElementIdentity = Anonymous> {
9 base: Div<K, NonFocusable, V>,
10 path: Option<SharedString>,
11}
12
13pub fn svg<V>() -> Svg<V, Anonymous>
14where
15 V: 'static + Send + Sync,
16{
17 Svg {
18 base: div(),
19 path: None,
20 }
21}
22
23impl<V, K> Svg<V, K>
24where
25 V: 'static + Send + Sync,
26 K: ElementIdentity,
27{
28 pub fn path(mut self, path: impl Into<SharedString>) -> Self {
29 self.path = Some(path.into());
30 self
31 }
32}
33
34impl<V: 'static + Send + Sync> Svg<V, Anonymous> {
35 pub fn id(self, id: impl Into<ElementId>) -> Svg<V, Identified> {
36 Svg {
37 base: self.base.id(id),
38 path: self.path,
39 }
40 }
41}
42
43impl<V, K> IntoAnyElement<V> for Svg<V, K>
44where
45 V: 'static + Send + Sync,
46 K: ElementIdentity,
47{
48 fn into_any(self) -> AnyElement<V> {
49 AnyElement::new(self)
50 }
51}
52
53impl<V, K> Element for Svg<V, K>
54where
55 V: 'static + Send + Sync,
56 K: ElementIdentity,
57{
58 type ViewState = V;
59 type ElementState = DivState;
60
61 fn id(&self) -> Option<crate::ElementId> {
62 self.base.id()
63 }
64
65 fn layout(
66 &mut self,
67 view: &mut V,
68 element_state: Option<Self::ElementState>,
69 cx: &mut crate::ViewContext<V>,
70 ) -> (LayoutId, Self::ElementState)
71 where
72 Self: Sized,
73 {
74 self.base.layout(view, element_state, cx)
75 }
76
77 fn paint(
78 &mut self,
79 bounds: Bounds<Pixels>,
80 view: &mut Self::ViewState,
81 element_state: &mut Self::ElementState,
82 cx: &mut crate::ViewContext<V>,
83 ) where
84 Self: Sized,
85 {
86 self.base.paint(bounds, view, element_state, cx);
87 let color = self
88 .base
89 .compute_style(bounds, element_state, cx)
90 .text
91 .color;
92 if let Some((path, color)) = self.path.as_ref().zip(color) {
93 cx.paint_svg(bounds, path.clone(), color).log_err();
94 }
95 }
96}
97
98impl<V, K> Styled for Svg<V, K>
99where
100 V: 'static + Send + Sync,
101 K: ElementIdentity,
102{
103 fn style(&mut self) -> &mut StyleRefinement {
104 self.base.style()
105 }
106}
107
108impl<V, K> Interactive for Svg<V, K>
109where
110 V: 'static + Send + Sync,
111 K: ElementIdentity,
112{
113 fn listeners(&mut self) -> &mut EventListeners<V> {
114 self.base.listeners()
115 }
116}
117
118impl<V, K> Hover for Svg<V, K>
119where
120 V: 'static + Send + Sync,
121 K: ElementIdentity,
122{
123 fn set_hover_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
124 self.base.set_hover_style(group, style);
125 }
126}
127
128impl<V> Click for Svg<V, Identified> where V: 'static + Send + Sync {}
129
130impl<V> Active for Svg<V, Identified>
131where
132 V: 'static + Send + Sync,
133{
134 fn set_active_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
135 self.base.set_active_style(group, style)
136 }
137}