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,
 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: 'static>() -> Svg<V, StatelessInteraction<V>, FocusDisabled> {
 19    Svg {
 20        base: div(),
 21        path: None,
 22    }
 23}
 24
 25impl<V, I, F> Svg<V, I, F>
 26where
 27    I: ElementInteraction<V>,
 28    F: ElementFocus<V>,
 29{
 30    pub fn path(mut self, path: impl Into<SharedString>) -> Self {
 31        self.path = Some(path.into());
 32        self
 33    }
 34}
 35
 36impl<V, F> Svg<V, StatelessInteraction<V>, F>
 37where
 38    F: ElementFocus<V>,
 39{
 40    pub fn id(self, id: impl Into<ElementId>) -> Svg<V, StatefulInteraction<V>, F> {
 41        Svg {
 42            base: self.base.id(id),
 43            path: self.path,
 44        }
 45    }
 46}
 47
 48impl<V, I, F> IntoAnyElement<V> for Svg<V, I, F>
 49where
 50    I: ElementInteraction<V>,
 51    F: ElementFocus<V>,
 52{
 53    fn into_any(self) -> AnyElement<V> {
 54        AnyElement::new(self)
 55    }
 56}
 57
 58impl<V, I, F> Element for Svg<V, I, F>
 59where
 60    I: ElementInteraction<V>,
 61    F: ElementFocus<V>,
 62{
 63    type ViewState = V;
 64    type ElementState = DivState;
 65
 66    fn id(&self) -> Option<crate::ElementId> {
 67        self.base.id()
 68    }
 69
 70    fn initialize(
 71        &mut self,
 72        view_state: &mut V,
 73        element_state: Option<Self::ElementState>,
 74        cx: &mut ViewContext<V>,
 75    ) -> Self::ElementState {
 76        self.base.initialize(view_state, element_state, cx)
 77    }
 78
 79    fn layout(
 80        &mut self,
 81        view_state: &mut V,
 82        element_state: &mut Self::ElementState,
 83        cx: &mut ViewContext<Self::ViewState>,
 84    ) -> LayoutId {
 85        self.base.layout(view_state, element_state, cx)
 86    }
 87
 88    fn paint(
 89        &mut self,
 90        bounds: Bounds<Pixels>,
 91        view: &mut Self::ViewState,
 92        element_state: &mut Self::ElementState,
 93        cx: &mut ViewContext<V>,
 94    ) where
 95        Self: Sized,
 96    {
 97        self.base.paint(bounds, view, element_state, cx);
 98        let color = self
 99            .base
100            .compute_style(bounds, element_state, cx)
101            .text
102            .color;
103        if let Some((path, color)) = self.path.as_ref().zip(color) {
104            cx.paint_svg(bounds, path.clone(), color).log_err();
105        }
106    }
107}
108
109impl<V, I, F> Styled for Svg<V, I, F>
110where
111    I: ElementInteraction<V>,
112    F: ElementFocus<V>,
113{
114    fn style(&mut self) -> &mut StyleRefinement {
115        self.base.style()
116    }
117}
118
119impl<V, I, F> StatelessInteractive for Svg<V, I, F>
120where
121    I: ElementInteraction<V>,
122    F: ElementFocus<V>,
123{
124    fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V> {
125        self.base.stateless_interaction()
126    }
127}
128
129impl<V, F> StatefulInteractive for Svg<V, StatefulInteraction<V>, F>
130where
131    V: 'static,
132    F: ElementFocus<V>,
133{
134    fn stateful_interaction(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
135        self.base.stateful_interaction()
136    }
137}
138
139impl<V: 'static, I> Focusable for Svg<V, I, FocusEnabled<V>>
140where
141    I: ElementInteraction<V>,
142{
143    fn focus_listeners(&mut self) -> &mut FocusListeners<Self::ViewState> {
144        self.base.focus_listeners()
145    }
146
147    fn set_focus_style(&mut self, style: StyleRefinement) {
148        self.base.set_focus_style(style)
149    }
150
151    fn set_focus_in_style(&mut self, style: StyleRefinement) {
152        self.base.set_focus_in_style(style)
153    }
154
155    fn set_in_focus_style(&mut self, style: StyleRefinement) {
156        self.base.set_in_focus_style(style)
157    }
158}