widget_forge/
scene.rs

1use crate::{prelude::*, widget::conditional_widgets::ConditionalWidgets};
2
3use ascii_forge::prelude::*;
4
5use std::{collections::HashSet, io, time::Duration};
6
7pub struct Scene<D> {
8    window: Window,
9    data: D,
10    widgets: Vec<Box<dyn Widget<D>>>,
11    special_widgets: Vec<Box<dyn SpecialWidget<D>>>,
12}
13
14impl<D: 'static> Scene<D> {
15    pub fn new(window: Window, data: D) -> Self {
16        Self {
17            window,
18            data,
19            widgets: vec![],
20            special_widgets: vec![],
21        }
22    }
23
24    pub fn data(&self) -> &D {
25        &self.data
26    }
27
28    pub fn data_mut(&mut self) -> &mut D {
29        &mut self.data
30    }
31
32    pub fn insert_widget(&mut self, widget: impl Widget<D> + 'static) -> &mut Self {
33        self.widgets.push(Box::new(widget));
34        self
35    }
36
37    pub fn insert_widgets(&mut self, set: impl WidgetSet<D>) -> &mut Self {
38        set.insert(self);
39        self
40    }
41
42    pub fn insert_special_widget(&mut self, widget: impl SpecialWidget<D> + 'static) -> &mut Self {
43        self.special_widgets.push(Box::new(widget));
44        self
45    }
46
47    pub fn insert_conditional_widgets(
48        &mut self,
49        cond: impl Fn(&mut Window, &mut D) -> bool + 'static,
50        widgets: impl WidgetSet<D>,
51    ) -> &mut Self {
52        let start = self.widgets.len();
53        widgets.insert(self);
54        let end = self.widgets.len();
55
56        self.insert_special_widget(ConditionalWidgets::new(cond, (start..end).collect()));
57        self
58    }
59
60    pub fn take_all(self) -> (Window, D) {
61        (self.window, self.data)
62    }
63
64    pub fn update(&mut self) {
65        let mut updated = HashSet::default();
66        for special in &mut self.special_widgets {
67            special.update(
68                &mut self.window,
69                &mut self.data,
70                &mut self.widgets,
71                &mut updated,
72            );
73        }
74        for (i, widget) in self.widgets.iter_mut().enumerate() {
75            if updated.contains(&i) {
76                continue;
77            }
78
79            widget.update(&mut self.window, &mut self.data);
80        }
81    }
82
83    pub fn run(
84        &mut self,
85        update_millis: u64,
86        run_cond: impl Fn(&mut Self) -> bool,
87    ) -> io::Result<&mut Self> {
88        while run_cond(self) {
89            self.update();
90
91            self.window.update(Duration::from_millis(update_millis))?;
92        }
93        Ok(self)
94    }
95}