svg.rs

  1use crate::{
  2    div, AnyElement, Bounds, Div, DivState, Element, ElementFocus, ElementId, ElementInteraction,
  3    FocusDisabled, FocusEnabled, FocusListeners, Focusable, IntoAnyElement, LayoutId, Pixels,
  4    SharedString, StatefulInteraction, StatefulInteractive, StatelessInteraction,
  5    StatelessInteractive, StyleRefinement, Styled, ViewContext,
  6};
  7use util::ResultExt;
  8
  9pub struct Svg<
 10    V: 'static + Send + Sync,
 11    I: ElementInteraction<V> = StatelessInteraction<V>,
 12    F: ElementFocus<V> = FocusDisabled,
 13> {
 14    base: Div<V, I, F>,
 15    path: Option<SharedString>,
 16}
 17
 18pub fn svg<V>() -> Svg<V, StatelessInteraction<V>, FocusDisabled>
 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: ElementInteraction<V>,
 32    F: ElementFocus<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, StatelessInteraction<V>, F>
 41where
 42    V: 'static + Send + Sync,
 43    F: ElementFocus<V>,
 44{
 45    pub fn id(self, id: impl Into<ElementId>) -> Svg<V, StatefulInteraction<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: ElementInteraction<V>,
 57    F: ElementFocus<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: ElementInteraction<V>,
 68    F: ElementFocus<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: ElementInteraction<V>,
120    F: ElementFocus<V>,
121{
122    fn style(&mut self) -> &mut StyleRefinement {
123        self.base.style()
124    }
125}
126
127impl<V, I, F> StatelessInteractive for Svg<V, I, F>
128where
129    V: 'static + Send + Sync,
130    I: ElementInteraction<V>,
131    F: ElementFocus<V>,
132{
133    fn stateless_interactivity(&mut self) -> &mut StatelessInteraction<V> {
134        self.base.stateless_interactivity()
135    }
136}
137
138impl<V, F> StatefulInteractive for Svg<V, StatefulInteraction<V>, F>
139where
140    V: 'static + Send + Sync,
141    F: ElementFocus<V>,
142{
143    fn stateful_interaction(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
144        self.base.stateful_interaction()
145    }
146}
147
148impl<V, I> Focusable for Svg<V, I, FocusEnabled<V>>
149where
150    V: 'static + Send + Sync,
151    I: ElementInteraction<V>,
152{
153    fn focus_listeners(&mut self) -> &mut FocusListeners<Self::ViewState> {
154        self.base.focus_listeners()
155    }
156
157    fn set_focus_style(&mut self, style: StyleRefinement) {
158        self.base.set_focus_style(style)
159    }
160
161    fn set_focus_in_style(&mut self, style: StyleRefinement) {
162        self.base.set_focus_in_style(style)
163    }
164
165    fn set_in_focus_style(&mut self, style: StyleRefinement) {
166        self.base.set_in_focus_style(style)
167    }
168}