svg.rs

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