svg.rs

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