1use crate::{
2 div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementFocusability,
3 ElementId, ElementIdentity, EventListeners, Focus, Focusable, Hover, Identified, Interactive,
4 IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString, StyleRefinement, Styled,
5 ViewContext,
6};
7use util::ResultExt;
8
9pub struct Svg<
10 V: 'static + Send + Sync,
11 I: ElementIdentity = Anonymous,
12 F: ElementFocusability = NonFocusable,
13> {
14 base: Div<V, I, F>,
15 path: Option<SharedString>,
16}
17
18pub fn svg<V>() -> Svg<V, Anonymous, NonFocusable>
19where
20 V: 'static + Send + Sync,
21{
22 Svg {
23 base: div(),
24 path: None,
25 }
26}
27
28impl<V, I, F> Svg<V, I, F>
29where
30 V: 'static + Send + Sync,
31 I: ElementIdentity,
32 F: ElementFocusability,
33{
34 pub fn path(mut self, path: impl Into<SharedString>) -> Self {
35 self.path = Some(path.into());
36 self
37 }
38}
39
40impl<V, F> Svg<V, Anonymous, F>
41where
42 V: 'static + Send + Sync,
43 F: ElementFocusability,
44{
45 pub fn id(self, id: impl Into<ElementId>) -> Svg<V, Identified, F> {
46 Svg {
47 base: self.base.id(id),
48 path: self.path,
49 }
50 }
51}
52
53impl<V, I, F> IntoAnyElement<V> for Svg<V, I, F>
54where
55 V: 'static + Send + Sync,
56 I: ElementIdentity,
57 F: ElementFocusability,
58{
59 fn into_any(self) -> AnyElement<V> {
60 AnyElement::new(self)
61 }
62}
63
64impl<V, I, F> Element for Svg<V, I, F>
65where
66 V: 'static + Send + Sync,
67 I: ElementIdentity,
68 F: ElementFocusability,
69{
70 type ViewState = V;
71 type ElementState = DivState;
72
73 fn id(&self) -> Option<crate::ElementId> {
74 self.base.id()
75 }
76
77 fn initialize(
78 &mut self,
79 view_state: &mut V,
80 element_state: Option<Self::ElementState>,
81 cx: &mut ViewContext<V>,
82 ) -> Self::ElementState {
83 self.base.initialize(view_state, element_state, cx)
84 }
85
86 fn layout(
87 &mut self,
88 view_state: &mut V,
89 element_state: &mut Self::ElementState,
90 cx: &mut ViewContext<Self::ViewState>,
91 ) -> LayoutId {
92 self.base.layout(view_state, element_state, cx)
93 }
94
95 fn paint(
96 &mut self,
97 bounds: Bounds<Pixels>,
98 view: &mut Self::ViewState,
99 element_state: &mut Self::ElementState,
100 cx: &mut ViewContext<V>,
101 ) where
102 Self: Sized,
103 {
104 self.base.paint(bounds, view, element_state, cx);
105 let color = self
106 .base
107 .compute_style(bounds, element_state, cx)
108 .text
109 .color;
110 if let Some((path, color)) = self.path.as_ref().zip(color) {
111 cx.paint_svg(bounds, path.clone(), color).log_err();
112 }
113 }
114}
115
116impl<V, I, F> Styled for Svg<V, I, F>
117where
118 V: 'static + Send + Sync,
119 I: ElementIdentity,
120 F: ElementFocusability,
121{
122 fn style(&mut self) -> &mut StyleRefinement {
123 self.base.style()
124 }
125}
126
127impl<V, I, F> Interactive for Svg<V, I, F>
128where
129 V: 'static + Send + Sync,
130 I: ElementIdentity,
131 F: ElementFocusability,
132{
133 fn listeners(&mut self) -> &mut EventListeners<V> {
134 self.base.listeners()
135 }
136}
137
138impl<V, I, F> Hover for Svg<V, I, F>
139where
140 V: 'static + Send + Sync,
141 I: ElementIdentity,
142 F: ElementFocusability,
143{
144 fn set_hover_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
145 self.base.set_hover_style(group, style);
146 }
147}
148
149impl<V, F> Click for Svg<V, Identified, F>
150where
151 V: 'static + Send + Sync,
152 F: ElementFocusability,
153{
154}
155
156impl<V, F> Active for Svg<V, Identified, F>
157where
158 V: 'static + Send + Sync,
159 F: ElementFocusability,
160{
161 fn set_active_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
162 self.base.set_active_style(group, style)
163 }
164}
165
166impl<V, I> Focus for Svg<V, I, Focusable>
167where
168 V: 'static + Send + Sync,
169 I: ElementIdentity,
170{
171 fn set_focus_style(&mut self, style: StyleRefinement) {
172 self.base.set_focus_style(style)
173 }
174
175 fn set_focus_in_style(&mut self, style: StyleRefinement) {
176 self.base.set_focus_in_style(style)
177 }
178
179 fn set_in_focus_style(&mut self, style: StyleRefinement) {
180 self.base.set_in_focus_style(style)
181 }
182
183 fn handle(&self) -> &crate::FocusHandle {
184 self.base.handle()
185 }
186}