svg.rs

  1use crate::{
  2    div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementId,
  3    ElementIdentity, EventListeners, Hover, Identified, Interactive, IntoAnyElement, LayoutId,
  4    NonFocusable, Pixels, SharedString, StyleRefinement, Styled,
  5};
  6use util::ResultExt;
  7
  8pub struct Svg<V: 'static + Send + Sync, K: ElementIdentity = Anonymous> {
  9    base: Div<K, NonFocusable, V>,
 10    path: Option<SharedString>,
 11}
 12
 13pub fn svg<V>() -> Svg<V, Anonymous>
 14where
 15    V: 'static + Send + Sync,
 16{
 17    Svg {
 18        base: div(),
 19        path: None,
 20    }
 21}
 22
 23impl<V, K> Svg<V, K>
 24where
 25    V: 'static + Send + Sync,
 26    K: ElementIdentity,
 27{
 28    pub fn path(mut self, path: impl Into<SharedString>) -> Self {
 29        self.path = Some(path.into());
 30        self
 31    }
 32}
 33
 34impl<V: 'static + Send + Sync> Svg<V, Anonymous> {
 35    pub fn id(self, id: impl Into<ElementId>) -> Svg<V, Identified> {
 36        Svg {
 37            base: self.base.id(id),
 38            path: self.path,
 39        }
 40    }
 41}
 42
 43impl<V, K> IntoAnyElement<V> for Svg<V, K>
 44where
 45    V: 'static + Send + Sync,
 46    K: ElementIdentity,
 47{
 48    fn into_any(self) -> AnyElement<V> {
 49        AnyElement::new(self)
 50    }
 51}
 52
 53impl<V, K> Element for Svg<V, K>
 54where
 55    V: 'static + Send + Sync,
 56    K: ElementIdentity,
 57{
 58    type ViewState = V;
 59    type ElementState = DivState;
 60
 61    fn id(&self) -> Option<crate::ElementId> {
 62        self.base.id()
 63    }
 64
 65    fn layout(
 66        &mut self,
 67        view: &mut V,
 68        element_state: Option<Self::ElementState>,
 69        cx: &mut crate::ViewContext<V>,
 70    ) -> (LayoutId, Self::ElementState)
 71    where
 72        Self: Sized,
 73    {
 74        self.base.layout(view, element_state, cx)
 75    }
 76
 77    fn paint(
 78        &mut self,
 79        bounds: Bounds<Pixels>,
 80        view: &mut Self::ViewState,
 81        element_state: &mut Self::ElementState,
 82        cx: &mut crate::ViewContext<V>,
 83    ) where
 84        Self: Sized,
 85    {
 86        self.base.paint(bounds, view, element_state, cx);
 87        let color = self
 88            .base
 89            .compute_style(bounds, element_state, cx)
 90            .text
 91            .color;
 92        if let Some((path, color)) = self.path.as_ref().zip(color) {
 93            cx.paint_svg(bounds, path.clone(), color).log_err();
 94        }
 95    }
 96}
 97
 98impl<V, K> Styled for Svg<V, K>
 99where
100    V: 'static + Send + Sync,
101    K: ElementIdentity,
102{
103    fn style(&mut self) -> &mut StyleRefinement {
104        self.base.style()
105    }
106}
107
108impl<V, K> Interactive for Svg<V, K>
109where
110    V: 'static + Send + Sync,
111    K: ElementIdentity,
112{
113    fn listeners(&mut self) -> &mut EventListeners<V> {
114        self.base.listeners()
115    }
116}
117
118impl<V, K> Hover for Svg<V, K>
119where
120    V: 'static + Send + Sync,
121    K: ElementIdentity,
122{
123    fn set_hover_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
124        self.base.set_hover_style(group, style);
125    }
126}
127
128impl<V> Click for Svg<V, Identified> where V: 'static + Send + Sync {}
129
130impl<V> Active for Svg<V, Identified>
131where
132    V: 'static + Send + Sync,
133{
134    fn set_active_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
135        self.base.set_active_style(group, style)
136    }
137}