1use crate::{
2 application::Application,
3 interactive::default_interactions_engine::DefaultInteractionsEngine,
4 layout::{CoordsMapping, default_layout_engine::DefaultLayoutEngine},
5};
6
7pub trait AppCycleFrameRunner<T> {
8 fn run_frame(self, tester: &mut AppCycleTester<T>);
9}
10
11impl<T> AppCycleFrameRunner<T> for () {
12 fn run_frame(self, _: &mut AppCycleTester<T>) {}
13}
14
15impl<T, F> AppCycleFrameRunner<T> for F
16where
17 F: FnMut(&mut AppCycleTester<T>),
18{
19 fn run_frame(mut self, tester: &mut AppCycleTester<T>) {
20 (self)(tester);
21 }
22}
23
24pub struct AppCycleTester<T> {
25 pub coords_mapping: CoordsMapping,
26 pub application: Application,
27 pub layout_engine: DefaultLayoutEngine,
28 pub interactions_engine: DefaultInteractionsEngine,
29 pub user_data: T,
30}
31
32impl<T> AppCycleTester<T> {
33 pub fn new(coords_mapping: CoordsMapping, user_data: T) -> Self {
34 Self {
35 coords_mapping,
36 application: Default::default(),
37 layout_engine: Default::default(),
38 interactions_engine: Default::default(),
39 user_data,
40 }
41 }
42
43 pub fn run_frame(&mut self, frame_runner: impl AppCycleFrameRunner<T>) {
44 frame_runner.run_frame(self);
45 if self.application.process() {
46 self.application
47 .layout(&self.coords_mapping, &mut self.layout_engine)
48 .unwrap();
49 }
50 self.application
51 .interact(&mut self.interactions_engine)
52 .unwrap();
53 }
54}