1use std::rc::Rc;
2
3use crate::modifier::Size;
4use crate::text::AppContextTextMeasurer;
5use cranpose_ui_graphics::{DrawPrimitive, DrawScope, DrawScopeDefault};
6
7pub type DrawCommandFn = Rc<dyn Fn(&mut DrawScopeDefault)>;
13
14#[derive(Clone)]
15pub enum DrawCommand {
16 Behind(DrawCommandFn),
17 WithContent(DrawCommandFn),
18 Overlay(DrawCommandFn),
19}
20
21pub fn command_draw_scope(size: Size) -> DrawScopeDefault {
24 DrawScopeDefault::with_text_measurer(size, AppContextTextMeasurer::shared())
25}
26
27pub fn command_draw_scope_reusing(size: Size, storage: Vec<DrawPrimitive>) -> DrawScopeDefault {
31 DrawScopeDefault::with_text_measurer_reusing(size, AppContextTextMeasurer::shared(), storage)
32}
33
34pub fn command_draw_scope_retained(
39 size: Size,
40 recording: cranpose_ui_graphics::CommandRecording,
41 out: Vec<DrawPrimitive>,
42) -> DrawScopeDefault {
43 DrawScopeDefault::with_recording(size, Some(AppContextTextMeasurer::shared()), recording, out)
44}
45
46#[derive(Default, Clone)]
47pub struct DrawCacheBuilder {
48 behind: Vec<DrawCommandFn>,
49 with_content: Vec<DrawCommandFn>,
50 overlay: Vec<DrawCommandFn>,
51}
52
53impl DrawCacheBuilder {
54 pub fn on_draw_behind(&mut self, f: impl Fn(&mut dyn DrawScope) + 'static) {
55 self.behind
56 .push(Rc::new(move |scope: &mut DrawScopeDefault| f(scope)));
57 }
58
59 pub fn on_draw_with_content(&mut self, f: impl Fn(&mut dyn DrawScope) + 'static) {
60 self.with_content
61 .push(Rc::new(move |scope: &mut DrawScopeDefault| f(scope)));
62 }
63
64 pub fn finish(self) -> Vec<DrawCommand> {
65 let mut commands = Vec::new();
66 commands.extend(self.behind.into_iter().map(DrawCommand::Behind));
67 commands.extend(self.with_content.into_iter().map(DrawCommand::WithContent));
68 commands.extend(self.overlay.into_iter().map(DrawCommand::Overlay));
69 commands
70 }
71}
72
73pub fn execute_draw_commands(commands: &[DrawCommand], size: Size) -> Vec<DrawPrimitive> {
74 let mut primitives = Vec::new();
75 for command in commands {
76 match command {
77 DrawCommand::Behind(f) | DrawCommand::WithContent(f) | DrawCommand::Overlay(f) => {
78 let mut scope = command_draw_scope(size);
79 f(&mut scope);
80 primitives.extend(scope.into_primitives());
81 }
82 }
83 }
84 primitives
85}