Skip to main content

cranpose_ui/
draw.rs

1use std::rc::Rc;
2
3use crate::modifier::Size;
4use cranpose_ui_graphics::{DrawPrimitive, DrawScope, DrawScopeDefault};
5
6pub type DrawCommandFn = Rc<dyn Fn(Size) -> Vec<DrawPrimitive>>;
7
8#[derive(Clone)]
9pub enum DrawCommand {
10    Behind(DrawCommandFn),
11    WithContent(DrawCommandFn),
12    Overlay(DrawCommandFn),
13}
14
15#[derive(Default, Clone)]
16pub struct DrawCacheBuilder {
17    behind: Vec<DrawCommandFn>,
18    with_content: Vec<DrawCommandFn>,
19    overlay: Vec<DrawCommandFn>,
20}
21
22impl DrawCacheBuilder {
23    pub fn on_draw_behind(&mut self, f: impl Fn(&mut dyn DrawScope) + 'static) {
24        let func = Rc::new(move |size: Size| {
25            let mut scope = DrawScopeDefault::new(size);
26            f(&mut scope);
27            scope.into_primitives()
28        });
29        self.behind.push(func);
30    }
31
32    pub fn on_draw_with_content(&mut self, f: impl Fn(&mut dyn DrawScope) + 'static) {
33        let func = Rc::new(move |size: Size| {
34            let mut scope = DrawScopeDefault::new(size);
35            f(&mut scope);
36            scope.into_primitives()
37        });
38        self.with_content.push(func);
39    }
40
41    pub fn finish(self) -> Vec<DrawCommand> {
42        let mut commands = Vec::new();
43        commands.extend(self.behind.into_iter().map(DrawCommand::Behind));
44        commands.extend(self.with_content.into_iter().map(DrawCommand::WithContent));
45        commands.extend(self.overlay.into_iter().map(DrawCommand::Overlay));
46        commands
47    }
48}
49
50pub fn execute_draw_commands(commands: &[DrawCommand], size: Size) -> Vec<DrawPrimitive> {
51    let mut primitives = Vec::new();
52    for command in commands {
53        match command {
54            DrawCommand::Behind(f) | DrawCommand::WithContent(f) | DrawCommand::Overlay(f) => {
55                primitives.extend(f(size));
56            }
57        }
58    }
59    primitives
60}