Skip to main content

ravenrs_widgets/
canvas.rs

1use std::fmt;
2use std::rc::Rc;
3
4use ravenrs_core::{Rect, Scene};
5use ravenrs_layout::LayoutStyle;
6
7use crate::View;
8use crate::context::{BuildCx, DrawFn, NodeId, Paint};
9
10/// A box of a given size that draws whatever its closure appends to the scene.
11/// The closure receives the box's absolute frame in logical pixels.
12///
13/// ```
14/// use ravenrs_core::{Color, Quad};
15/// use ravenrs_widgets::Canvas;
16///
17/// let bars = Canvas::new(|frame, scene| {
18///     for (i, v) in [0.4_f32, 0.9, 0.6].iter().enumerate() {
19///         let h = frame.height() * v;
20///         let x = frame.x() + i as f32 * 24.0;
21///         let bar = ravenrs_core::Rect::new(x, frame.max_y() - h, 16.0, h);
22///         scene.push_quad(Quad::new(bar, Color::hex(0x4c66ee)).radius(4.0));
23///     }
24/// })
25/// .size(72.0, 48.0);
26/// ```
27#[cfg_attr(feature = "live", ravenrs_live::expose(part = "fields"))]
28pub struct Canvas {
29    draw: DrawFn,
30    style: LayoutStyle,
31}
32
33impl fmt::Debug for Canvas {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        f.debug_struct("Canvas").field("style", &self.style).finish_non_exhaustive()
36    }
37}
38
39#[cfg_attr(feature = "live", ravenrs_live::expose)]
40impl Canvas {
41    /// A canvas drawn by `draw`, called on every paint with the absolute frame.
42    pub fn new(draw: impl Fn(Rect, &mut Scene) + 'static) -> Self {
43        Self { draw: Rc::new(draw), style: LayoutStyle::leaf() }
44    }
45
46    /// Fixed size in logical pixels.
47    pub fn size(mut self, width: f32, height: f32) -> Self {
48        self.style.width = Some(width);
49        self.style.height = Some(height);
50        self
51    }
52
53    /// Fills the free space along the parent stack's axis.
54    pub fn grow(mut self, grow: f32) -> Self {
55        self.style.grow = grow;
56        self
57    }
58}
59
60impl View for Canvas {
61    fn build(&self, cx: &mut BuildCx<'_>) -> NodeId {
62        cx.container(self.style, &[], Paint::Custom(self.draw.clone()))
63    }
64}