svg.rs

  1use crate::{
  2    div, Active, AnyElement, Bounds, Div, DivState, Element, ElementFocusability, ElementId,
  3    ElementInteractivity, Focus, FocusListeners, Focusable, Hover, IntoAnyElement, LayoutId,
  4    NonFocusable, Pixels, SharedString, StatefulInteractivity, StatefullyInteractive,
  5    StatelessInteractivity, StatelesslyInteractive, StyleRefinement, Styled, ViewContext,
  6};
  7use util::ResultExt;
  8
  9pub struct Svg<
 10    V: 'static + Send + Sync,
 11    I: ElementInteractivity<V> = StatelessInteractivity<V>,
 12    F: ElementFocusability<V> = NonFocusable,
 13> {
 14    base: Div<V, I, F>,
 15    path: Option<SharedString>,
 16}
 17
 18pub fn svg<V>() -> Svg<V, StatelessInteractivity<V>, 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: ElementInteractivity<V>,
 32    F: ElementFocusability<V>,
 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, StatelessInteractivity<V>, F>
 41where
 42    V: 'static + Send + Sync,
 43    F: ElementFocusability<V>,
 44{
 45    pub fn id(self, id: impl Into<ElementId>) -> Svg<V, StatefulInteractivity<V>, 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: ElementInteractivity<V>,
 57    F: ElementFocusability<V>,
 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: ElementInteractivity<V>,
 68    F: ElementFocusability<V>,
 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: ElementInteractivity<V>,
120    F: ElementFocusability<V>,
121{
122    fn style(&mut self) -> &mut StyleRefinement {
123        self.base.style()
124    }
125}
126
127impl<V, I, F> StatelesslyInteractive for Svg<V, I, F>
128where
129    V: 'static + Send + Sync,
130    I: ElementInteractivity<V>,
131    F: ElementFocusability<V>,
132{
133    fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
134        self.base.stateless_interactivity()
135    }
136}
137
138impl<V, I, F> Hover for Svg<V, I, F>
139where
140    V: 'static + Send + Sync,
141    I: ElementInteractivity<V>,
142    F: ElementFocusability<V>,
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> StatefullyInteractive for Svg<V, StatefulInteractivity<V>, F>
150where
151    V: 'static + Send + Sync,
152    F: ElementFocusability<V>,
153{
154    fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<Self::ViewState> {
155        self.base.stateful_interactivity()
156    }
157}
158
159impl<V, F> Active for Svg<V, StatefulInteractivity<V>, F>
160where
161    V: 'static + Send + Sync,
162    F: ElementFocusability<V>,
163{
164    fn set_active_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
165        self.base.set_active_style(group, style)
166    }
167}
168
169impl<V, I> Focus for Svg<V, I, Focusable<V>>
170where
171    V: 'static + Send + Sync,
172    I: ElementInteractivity<V>,
173{
174    fn focus_listeners(&mut self) -> &mut FocusListeners<Self::ViewState> {
175        self.base.focus_listeners()
176    }
177
178    fn set_focus_style(&mut self, style: StyleRefinement) {
179        self.base.set_focus_style(style)
180    }
181
182    fn set_focus_in_style(&mut self, style: StyleRefinement) {
183        self.base.set_focus_in_style(style)
184    }
185
186    fn set_in_focus_style(&mut self, style: StyleRefinement) {
187        self.base.set_in_focus_style(style)
188    }
189
190    fn handle(&self) -> &crate::FocusHandle {
191        self.base.handle()
192    }
193}