embedded_multi_page_hmi/page/
basic.rs

1use super::super::{
2    Interaction, PageBaseInterface, PageError, PageInteractionInterface, PageLifetime,
3    PageNavigation,
4};
5
6/// A basic page has at least a title and an optional lifetime
7///
8/// A basic page can be used to construct other pages, since every pages
9/// is supposed to have a title and an optional lifetime.
10pub struct BasicPage {
11    pub title: &'static str,
12    pub lifetime: Option<PageLifetime>,
13}
14
15impl BasicPage {
16    pub fn new(title: &'static str, lifetime: Option<PageLifetime>) -> Self {
17        BasicPage { title, lifetime }
18    }
19}
20
21/// A text page holds a text as content and contains the behavior of a BasicPage
22pub struct TextPage {
23    pub basic: BasicPage,
24    pub text: &'static str,
25}
26
27impl TextPage {
28    pub fn new(basic: BasicPage, text: &'static str) -> Self {
29        TextPage { basic, text }
30    }
31}
32
33impl PageBaseInterface for TextPage {
34    fn title(&self) -> &str {
35        self.basic.title
36    }
37
38    // Static page still need to take care for their own lifetime
39    fn update<'a>(
40        &mut self,
41        _title_of_subpages: Option<Box<dyn Iterator<Item = &'a str> + 'a>>,
42    ) -> Result<PageNavigation, PageError> {
43        match self.basic.lifetime {
44            Some(mut lifetime) => {
45                let mut result = PageNavigation::Update;
46                lifetime.increase_age();
47                if lifetime.is_over() {
48                    lifetime.reset_age();
49                    result = lifetime.get_target();
50                }
51                self.basic.lifetime = Some(lifetime);
52                Ok(result)
53            }
54            None => Ok(PageNavigation::Update),
55        }
56    }
57}
58
59impl PageInteractionInterface for TextPage {}
60
61/// A startup page - optionally shown before stopping the HMI
62///
63/// * Is a text page with title "Startup"
64/// * Has a dedicated lifetime
65/// * Any user interaction is suppressed
66/// * If lifetime is over it turns to home page
67pub struct StartupPage(pub TextPage);
68
69impl StartupPage {
70    pub fn new(startup_message: &'static str, lifetime_in_updates: u16) -> Self {
71        let basic = BasicPage::new(
72            "Startup",
73            Some(PageLifetime::new(PageNavigation::Home, lifetime_in_updates)),
74        );
75        StartupPage(TextPage {
76            basic,
77            text: startup_message,
78        })
79    }
80}
81
82impl PageBaseInterface for StartupPage {
83    fn title(&self) -> &str {
84        self.0.title()
85    }
86
87    /// Update checks lifetime
88    ///
89    /// Return an error if lifetime is over
90    fn update<'a>(
91        &mut self,
92        _title_of_subpages: Option<Box<dyn Iterator<Item = &'a str> + 'a>>,
93    ) -> Result<PageNavigation, PageError> {
94        match self.0.basic.lifetime {
95            Some(mut lifetime) => {
96                let mut result = PageNavigation::SystemStart;
97                lifetime.increase_age();
98                if lifetime.is_over() {
99                    lifetime.reset_age();
100                    result = lifetime.get_target();
101                }
102                self.0.basic.lifetime = Some(lifetime);
103                Ok(result)
104            }
105            None => Ok(PageNavigation::SystemStart),
106        }
107    }
108}
109
110impl PageInteractionInterface for StartupPage {
111    /// Do not react on any interaction
112    fn dispatch(&mut self, _interaction: Interaction) -> PageNavigation {
113        PageNavigation::SystemStart
114    }
115}
116
117/// A shutdown page - optionally shown before stopping the HMI
118///
119/// * Is a text page with title "Shutdown"
120/// * Has a dedicated lifetime
121/// * Any user interaction is suppressed
122/// * If lifetime is over it turns returns an PageError
123pub struct ShutdownPage(pub TextPage);
124
125impl ShutdownPage {
126    pub fn new(shutdown_message: &'static str, lifetime_in_updates: u16) -> Self {
127        let basic = BasicPage::new(
128            "Shutdown",
129            Some(PageLifetime::new(
130                PageNavigation::SystemStop,
131                lifetime_in_updates,
132            )),
133        );
134        ShutdownPage(TextPage {
135            basic,
136            text: shutdown_message,
137        })
138    }
139}
140
141impl PageBaseInterface for ShutdownPage {
142    fn title(&self) -> &str {
143        self.0.title()
144    }
145
146    /// Update checks lifetime
147    ///
148    /// Return an error if lifetime is over
149    fn update<'a>(
150        &mut self,
151        _title_of_subpages: Option<Box<dyn Iterator<Item = &'a str> + 'a>>,
152    ) -> Result<PageNavigation, PageError> {
153        match self.0.basic.lifetime {
154            Some(mut lifetime) => {
155                lifetime.increase_age();
156                self.0.basic.lifetime = Some(lifetime);
157                if lifetime.is_over() {
158                    lifetime.reset_age();
159                    self.0.basic.lifetime = Some(lifetime);
160                    Err(PageError)
161                } else {
162                    Ok(PageNavigation::SystemStop)
163                }
164            }
165            None => Ok(PageNavigation::SystemStop),
166        }
167    }
168}
169
170impl PageInteractionInterface for ShutdownPage {
171    /// Do not react on any interaction
172    fn dispatch(&mut self, _interaction: Interaction) -> PageNavigation {
173        PageNavigation::SystemStop
174    }
175}
176
177#[cfg(test)]
178mod tests;