use refineable::Refineable as _; use crate::{ App, Bounds, Element, ElementId, GlobalElementId, IntoElement, Pixels, Style, StyleRefinement, Styled, Window, }; /// 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 Window, &mut App) -> T, paint: impl 'static + FnOnce(Bounds, T, &mut Window, &mut App), ) -> 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 Window, &mut App) -> T>>, paint: Option, T, &mut Window, &mut App)>>, 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 id(&self) -> Option { None } fn request_layout( &mut self, _id: Option<&GlobalElementId>, window: &mut Window, cx: &mut App, ) -> (crate::LayoutId, Self::RequestLayoutState) { let mut style = Style::default(); style.refine(&self.style); let layout_id = window.request_layout(style.clone(), [], cx); (layout_id, style) } fn prepaint( &mut self, _id: Option<&GlobalElementId>, bounds: Bounds, _request_layout: &mut Style, window: &mut Window, cx: &mut App, ) -> Option { Some(self.prepaint.take().unwrap()(bounds, window, cx)) } fn paint( &mut self, _id: Option<&GlobalElementId>, bounds: Bounds, style: &mut Style, prepaint: &mut Self::PrepaintState, window: &mut Window, cx: &mut App, ) { let prepaint = prepaint.take().unwrap(); style.paint(bounds, window, cx, |window, cx| { (self.paint.take().unwrap())(bounds, prepaint, window, cx) }); } } impl Styled for Canvas { fn style(&mut self) -> &mut crate::StyleRefinement { &mut self.style } }