use refineable::Refineable as _; use crate::{Bounds, Element, IntoElement, Pixels, Style, StyleRefinement, Styled, WindowContext}; /// Construct a canvas element with the given paint callback. /// Useful for adding short term custom drawing to a view. pub fn canvas( prepaint: impl 'static + FnOnce(Bounds, &mut WindowContext) -> T, paint: impl 'static + FnOnce(Bounds, T, &mut WindowContext), ) -> Canvas { Canvas { prepaint: Some(Box::new(prepaint)), paint: Some(Box::new(paint)), style: StyleRefinement::default(), } } /// A canvas element, meant for accessing the low level paint API without defining a whole /// custom element pub struct Canvas { prepaint: Option, &mut WindowContext) -> T>>, paint: Option, T, &mut WindowContext)>>, style: StyleRefinement, } impl IntoElement for Canvas { type Element = Self; fn into_element(self) -> Self::Element { self } } impl Element for Canvas { type RequestLayoutState = Style; type PrepaintState = Option; fn request_layout( &mut self, cx: &mut WindowContext, ) -> (crate::LayoutId, Self::RequestLayoutState) { let mut style = Style::default(); style.refine(&self.style); let layout_id = cx.request_layout(&style, []); (layout_id, style) } fn prepaint( &mut self, bounds: Bounds, _request_layout: &mut Style, cx: &mut WindowContext, ) -> Option { Some(self.prepaint.take().unwrap()(bounds, cx)) } fn paint( &mut self, bounds: Bounds, style: &mut Style, prepaint: &mut Self::PrepaintState, cx: &mut WindowContext, ) { let prepaint = prepaint.take().unwrap(); style.paint(bounds, cx, |cx| { (self.paint.take().unwrap())(bounds, prepaint, cx) }); } } impl Styled for Canvas { fn style(&mut self) -> &mut crate::StyleRefinement { &mut self.style } }