cosg 0.1.1

A wgpu-based UI library with a dark violet theme
Documentation
use crate::{
    esc::Esc,
    theme::Theme,
    widget::{DrawRect, Rect, TextCmd, Widget, WidgetEvent},
};

struct Cell { col: usize, row: usize, widget: Box<dyn Widget> }

pub struct Grid {
    cols:  usize,
    rows:  usize,
    cells: Vec<Cell>,
    gap:   f32,
    esc:   Esc,
    rect:  Rect,
}

impl Grid {
    pub fn new(cols: usize, rows: usize) -> Self {
        Self { cols, rows, cells: vec![], gap: 8.0, esc: Esc::default(), rect: Rect::default() }
    }
    pub fn gap(mut self, g: f32) -> Self { self.gap = g; self }
    pub fn esc(mut self, e: Esc) -> Self { self.esc = e; self }
    pub fn place(mut self, widget: impl Widget + 'static, col: usize, row: usize) -> Self {
        self.cells.push(Cell { col, row, widget: Box::new(widget) }); self
    }
}

impl Widget for Grid {
    fn layout(&mut self, bounds: Rect, theme: &Theme) {
        self.rect = bounds;
        let cell_w = (bounds.w - self.gap * (self.cols + 1) as f32) / self.cols as f32;
        let cell_h = (bounds.h - self.gap * (self.rows + 1) as f32) / self.rows as f32;
        for cell in &mut self.cells {
            let cx = bounds.x + self.gap + cell.col as f32 * (cell_w + self.gap);
            let cy = bounds.y + self.gap + cell.row as f32 * (cell_h + self.gap);
            cell.widget.layout(Rect::new(cx, cy, cell_w, cell_h), theme);
        }
    }

    fn draw(&self, theme: &Theme) -> Vec<DrawRect> {
        let mut out = vec![DrawRect {
            rect:          self.rect,
            color:         theme.bg,
            border_radius: self.esc.border_radius,
            border_width:  self.esc.border_width,
            border_color:  self.esc.border_color.unwrap_or(theme.border),
        }];
        for cell in &self.cells { out.extend(cell.widget.draw(theme)); }
        out
    }

    fn draw_text(&self, theme: &Theme) -> Vec<TextCmd> {
        self.cells.iter().flat_map(|c| c.widget.draw_text(theme)).collect()
    }

    fn handle_event(&mut self, event: &WidgetEvent) {
        for cell in &mut self.cells { cell.widget.handle_event(event); }
    }

    fn rect(&self) -> Rect { self.rect }
}