Skip to main content

cotis_modules_debug/layout_module_debugger/
capture.rs

1//! [`LayoutManager`] decorator that records layout output.
2//!
3//! Wrap your layout manager with [`LayoutModuleCapture`] during a record pass (stage 1) to
4//! capture the per-frame layout output for JSON persistence via
5//! [`store_computed_layout`](../fn.store_computed_layout.html).
6
7use cotis::element_configuring::ConfiguredParentElement;
8use cotis::layout::{LayoutFrameManager, LayoutManager, LayoutManagerCompatible};
9use serde::Serialize;
10
11/// Wraps a layout manager and accumulates layout output across frames.
12///
13/// Implements [`LayoutManager`] and
14/// [`LayoutManagerCompatible`], delegating all
15/// operations to the inner module while copying each frame's output into an internal
16/// vector accessible via [`output`](Self::output).
17///
18/// # Recommended usage
19///
20/// Use for **single-frame capture**: run one `compute_frame`, then call
21/// [`store_computed_layout`](../fn.store_computed_layout.html) with `output()`.
22///
23/// If used across multiple frames, `output()` grows unbounded — each frame's results are
24/// appended. There is no automatic reset; avoid multi-frame capture unless you manage the
25/// accumulated vector explicitly.
26pub struct LayoutModuleCapture<Module, ElementsOutput: Clone + Serialize> {
27    internal: Module,
28    output: Vec<ElementsOutput>,
29}
30
31impl<Module, ElementsOutput: Clone + Serialize> LayoutModuleCapture<Module, ElementsOutput> {
32    /// Creates a capture wrapper around an existing layout manager.
33    pub fn new(internal: Module) -> Self {
34        Self {
35            internal,
36            output: Vec::new(),
37        }
38    }
39
40    /// Returns all layout output accumulated so far across every captured frame.
41    pub fn output(&self) -> &Vec<ElementsOutput> {
42        &self.output
43    }
44}
45
46struct LayoutModuleFrameCapture<'layout, ElementsOutput, T> {
47    output: &'layout mut Vec<ElementsOutput>,
48    frame_manager: T,
49}
50
51impl<Module, ElementsOutput: Clone + Serialize, Render> LayoutManagerCompatible<Render>
52    for LayoutModuleCapture<Module, ElementsOutput>
53where
54    Module: LayoutManagerCompatible<Render>,
55{
56    fn init(&mut self, renderer: &mut Render) {
57        self.internal.init(renderer);
58    }
59    fn prepare(&mut self, render: &Render) {
60        self.internal.prepare(render);
61    }
62}
63
64impl<'frame, Module, ElementsOutput: 'frame + Clone + Serialize, ConfigType: 'frame>
65    LayoutManager<'frame, ConfigType, ElementsOutput>
66    for LayoutModuleCapture<Module, ElementsOutput>
67where
68    Module: LayoutManager<'frame, ConfigType, ElementsOutput>,
69{
70    type ElementConfigurer<'layout>
71        = Module::ElementConfigurer<'layout>
72    where
73        Self: 'layout,
74        ConfigType: 'frame,
75        ElementsOutput: 'frame;
76
77    fn begin_frame<'layout>(
78        &'layout mut self,
79    ) -> impl LayoutFrameManager<'frame, ConfigType, ElementsOutput, Self::ElementConfigurer<'layout>>
80    where
81        Self: 'layout,
82        ConfigType: 'frame,
83        ElementsOutput: 'frame,
84    {
85        let manager = self.internal.begin_frame();
86        LayoutModuleFrameCapture {
87            output: &mut self.output,
88            frame_manager: manager,
89        }
90    }
91}
92
93impl<'frame, ConfigType: 'frame, ElementsOutput: 'frame + Clone + Serialize, ElementConfigurer, T>
94    LayoutFrameManager<'frame, ConfigType, ElementsOutput, ElementConfigurer>
95    for LayoutModuleFrameCapture<'_, ElementsOutput, T>
96where
97    T: LayoutFrameManager<'frame, ConfigType, ElementsOutput, ElementConfigurer>,
98    ElementConfigurer: cotis::element_configuring::ConfigureElements<ConfigType>,
99{
100    fn begin(&'_ mut self) -> ConfiguredParentElement<'_, ElementConfigurer, ConfigType> {
101        self.frame_manager.begin()
102    }
103
104    fn end(self) -> impl Iterator<Item = ElementsOutput> {
105        let iter_output = self.frame_manager.end().collect::<Vec<_>>();
106        self.output.append(&mut iter_output.clone());
107        iter_output.into_iter()
108    }
109}