limn
    ↑↓ ChooseEnter OpenEsc Close
    GitHub

    Components/System

    Drawing

    What the application draws itself, for a shape no component makes: a track's waveform, a meter, a sketch. It draws in the frame's own commands, the ones every component is drawn in, so any backend paints it.

    Native componentGuide source

    Preview

    CodeSource
    fn waveform(levels: Vec<f32>, played: f32, ink: Color, rest: Color) -> Element {
        Element::drawing(move |size| {
            let pitch = size.width / levels.len().max(1) as f32;
            levels
                .iter()
                .enumerate()
                .map(|(index, level)| {
                    let x = index as f32 * pitch;
                    let height = size.height * level;
                    DrawCommand::FillRect {
                        rect: Rect::new(x, (size.height - height) / 2.0, pitch - 2.0, height),
                        color: if x < size.width * played { ink } else { rest },
                        radius: 1.5,
                    }
                })
                .collect()
        })
        .size(None, Some(64.0))
    }

    Examples

    Each one is the library drawing it. Press, type and hover.

    Drawing2 / 2
    CodeSource
    wave

    Drawing

    What the application draws itself, for a shape no component makes: a track’s waveform, a meter, a sketch. It draws in the frame’s own commands, the ones every component is drawn in, so any backend paints it.

    Import

    use limn::{Color, DrawCommand, Element, Rect};

    Usage

    Element::drawing takes a function of the size the element is laid out at and returns the commands to draw at it, placed from the element’s top-left corner.

    fn waveform(levels: Vec<f32>, played: f32, ink: Color, rest: Color) -> Element {
        Element::drawing(move |size| {
            let pitch = size.width / levels.len().max(1) as f32;
            levels
                .iter()
                .enumerate()
                .map(|(index, level)| {
                    let x = index as f32 * pitch;
                    let height = size.height * level;
                    DrawCommand::FillRect {
                        rect: Rect::new(x, (size.height - height) / 2.0, pitch - 2.0, height),
                        color: if x < size.width * played { ink } else { rest },
                        radius: 1.5,
                    }
                })
                .collect()
        })
        .size(None, Some(64.0))
    }

    The function runs each time the tree lays the window out, so the drawing follows its size. It owns what it draws from: move the values in, as levels is above.

    Size

    Give it a size. Alone it takes no height, and only the width a column stretches it to. Padding is kept around the drawing: the size the function is given is the box inside it.

    Clipping

    The tree moves the commands into place and clips them to the element’s box. A drawing may push clips of its own: one it leaves open is closed at its end, and a PopClip with no PushClip before it is left out, so no drawing can change the clipping of what comes after it.

    Pressing it

    A drawing is passive. To press it, wrap it as any element is wrapped: Element::clickable(id, drawing) reports Clicked with id, and Tooltip::new(drawing, id, title, palette) gives it a hint.

    Accessibility

    A drawing tells the platform nothing on its own. Name what it shows with .accessible(Access::new(Role::Image).id("waveform").name("Waveform")): a passive element has no ID of its own, so the node takes the one given here.

    API reference

    The guide covers composition, options and actions. Generate the complete Rust type and builder reference from the checkout:

    cargo doc -p limn --open

    Component API overview · State and actions

    The example is drawn by crates/limn-gallery/src/pages/drawing.rs.