kael_ui 0.2.0

Professional shadcn-inspired UI component library for Kael. 100+ accessible components for building beautiful, performant desktop applications.
//! Direct Kael painting surface with Styled support.

use kael::{prelude::FluentBuilder as _, *};
use std::rc::Rc;

type PaintCallback = Rc<dyn Fn(Bounds<Pixels>, &mut Window, &mut App)>;
type PrepareCallback = Rc<dyn Fn(Bounds<Pixels>, &mut Window, &mut App)>;

#[derive(IntoElement)]
pub struct CanvasComponent {
    id: ElementId,
    on_paint: Option<PaintCallback>,
    on_prepare: Option<PrepareCallback>,
    style: StyleRefinement,
}

impl CanvasComponent {
    pub fn new(id: impl Into<ElementId>) -> Self {
        Self {
            id: id.into(),
            on_paint: None,
            on_prepare: None,
            style: StyleRefinement::default(),
        }
    }

    pub fn on_paint(
        mut self,
        callback: impl Fn(Bounds<Pixels>, &mut Window, &mut App) + 'static,
    ) -> Self {
        self.on_paint = Some(Rc::new(callback));
        self
    }

    pub fn on_prepare(
        mut self,
        callback: impl Fn(Bounds<Pixels>, &mut Window, &mut App) + 'static,
    ) -> Self {
        self.on_prepare = Some(Rc::new(callback));
        self
    }
}

impl Styled for CanvasComponent {
    fn style(&mut self) -> &mut StyleRefinement {
        &mut self.style
    }
}

impl RenderOnce for CanvasComponent {
    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
        let user_style = self.style;
        let paint_cb = self.on_paint;
        let prepare_cb = self.on_prepare;

        div()
            .id(self.id)
            .relative()
            .child(
                canvas_with_prepaint(
                    move |bounds, window, cx| {
                        if let Some(ref cb) = prepare_cb {
                            cb(bounds, window, cx);
                        }
                    },
                    move |bounds, _, window, cx| {
                        if let Some(ref cb) = paint_cb {
                            cb(bounds, window, cx);
                        }
                    },
                )
                .absolute()
                .inset_0()
                .size_full(),
            )
            .map(|this| {
                let mut el = this;
                el.style().refine(&user_style);
                el
            })
    }
}