kaolin 0.1.10

A Rust library for flexible layouts, inspired by Clay
Documentation
extern crate std;

use std::{
    cell::RefCell,
    rc::{Rc, Weak},
};

use crate::{
    commands::RenderCommand,
    kaolin::{Kaolin, scope::KaolinScope},
    renderers::KaolinRenderer,
    style::{KaolinColor, TextStyle},
};
use raylib::prelude::*;

#[derive(Clone, Copy, PartialEq, Debug, Default)]
struct KRaylibColor {
    inner: raylib::color::Color,
}

impl From<KRaylibColor> for raylib::color::Color {
    fn from(value: KRaylibColor) -> Self {
        value.inner
    }
}

impl From<raylib::color::Color> for KRaylibColor {
    fn from(value: raylib::color::Color) -> Self {
        KRaylibColor { inner: value }
    }
}

impl KaolinColor<KRaylibColor> for KRaylibColor {
    fn default_foreground_color() -> KRaylibColor {
        KRaylibColor {
            inner: raylib::color::Color::BLACK,
        }
    }

    fn default_background_color() -> KRaylibColor {
        KRaylibColor {
            inner: raylib::color::Color::WHITE,
        }
    }
}

pub struct RaylibRenderer {
    kaolin: Kaolin<KRaylibColor>,
    raylib: Rc<RefCell<RaylibHandle>>,
    thread: RaylibThread,
}

impl RaylibRenderer {
    fn measure_text(
        this: Weak<RefCell<RaylibHandle>>,
        text: &str,
        config: &TextStyle<KRaylibColor>,
    ) -> (f64, f64) {
        let raylib = this.upgrade().unwrap();
        let raylib = raylib.borrow();
        let len = raylib.measure_text(text, config.font_size as i32);
        (len as f64, config.font_size as f64)
    }

    pub fn new(width: i32, height: i32) -> Self {
        let (raylib_handle, thread) = raylib::init()
            .size(width, height)
            .title("Kaolin Renderer")
            .build();
        let raylib = Rc::new(RefCell::new(raylib_handle));
        let weakref = Rc::downgrade(&raylib);

        RaylibRenderer {
            kaolin: Kaolin::new((width, height), move |text, config| {
                RaylibRenderer::measure_text(weakref.clone(), text, config)
            }),
            thread,
            raylib,
        }
    }

    pub fn should_close(&self) -> bool {
        let raylib = self.raylib.borrow();
        raylib.window_should_close()
    }
}

impl KaolinRenderer<KRaylibColor> for RaylibRenderer {
    fn draw(&mut self, draw_fn: impl Fn(KaolinScope<KRaylibColor>) -> KaolinScope<KRaylibColor>) {
        let commands = self.kaolin.draw(draw_fn);
        let mut raylib = self.raylib.borrow_mut();
        let mut d = raylib.begin_drawing(&self.thread);
        for command in commands {
            match command {
                RenderCommand::DrawRectangle {
                    x,
                    y,
                    width,
                    height,
                    color,
                    ..
                } => {
                    d.draw_rectangle(x as i32, y as i32, width as i32, height as i32, color.inner);
                }
                RenderCommand::DrawText {
                    text,
                    x,
                    y,
                    color,
                    font_size,
                    ..
                } => {
                    d.draw_text(
                        text.as_str(),
                        x as i32,
                        y as i32,
                        font_size as i32,
                        color.inner,
                    );
                }
            }
        }
    }
}