ferroui_browser/
browser_single_view_lifetime.rs1use crate::ferro_view::FerroView;
2use ferroui_base::Ref;
3use ferroui_controls::application_lifetimes::{
4 IApplicationLifetime, ISingleTopLevelApplicationLifetime, ISingleViewApplicationLifetime,
5};
6use ferroui_controls::{Control, TopLevel};
7use std::any::Any;
8use std::cell::RefCell;
9use std::rc::Rc;
10
11#[derive(Default)]
13pub struct BrowserSingleViewLifetime {
14 view: RefCell<Option<Rc<FerroView>>>,
15}
16
17impl BrowserSingleViewLifetime {
18 pub fn new() -> Rc<Self> {
21 Rc::new(Self::default())
22 }
23
24 pub fn view(&self) -> Option<Rc<FerroView>> {
26 self.view.borrow().clone()
27 }
28
29 pub fn set_view(&self, view: Option<Rc<FerroView>>) {
31 *self.view.borrow_mut() = view;
32 }
33
34 fn ensure_view(&self) -> Rc<FerroView> {
35 match self.view() {
36 Some(view) => view,
37 None => panic!(
38 "Browser lifetime was not initialized. Make sure AppBuilder::start_browser_app was called."
39 ),
40 }
41 }
42}
43
44impl IApplicationLifetime for BrowserSingleViewLifetime {
45 fn as_any(&self) -> &dyn Any {
46 self
47 }
48
49 fn as_single_view_application_lifetime(&self) -> Option<&dyn ISingleViewApplicationLifetime> {
50 Some(self)
51 }
52
53 fn as_single_top_level_application_lifetime(&self) -> Option<&dyn ISingleTopLevelApplicationLifetime> {
54 Some(self)
55 }
56}
57
58impl ISingleViewApplicationLifetime for BrowserSingleViewLifetime {
59 fn main_view(&self) -> Option<Ref<Control>> {
60 self.ensure_view().content()
61 }
62
63 fn set_main_view(&self, value: Option<Ref<Control>>) {
64 self.ensure_view().set_content(value);
65 }
66}
67
68impl ISingleTopLevelApplicationLifetime for BrowserSingleViewLifetime {
69 fn top_level(&self) -> Option<Ref<TopLevel>> {
70 self.view().map(|view| view.top_level())
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn a_lifetime_without_a_view_has_no_top_level() {
80 let lifetime = BrowserSingleViewLifetime::new();
81
82 assert!(lifetime.view().is_none());
83 assert!(lifetime.top_level().is_none());
84 }
85
86 #[test]
87 fn the_lifetime_is_a_single_view_and_single_top_level_lifetime() {
88 let lifetime = BrowserSingleViewLifetime::new();
89 let lifetime: &dyn IApplicationLifetime = &*lifetime;
90
91 assert!(lifetime.as_single_view_application_lifetime().is_some());
92 assert!(lifetime.as_single_top_level_application_lifetime().is_some());
93 assert!(lifetime.as_controlled_application_lifetime().is_none());
94 assert!(lifetime.as_classic_desktop_style_application_lifetime().is_none());
95 }
96
97 #[test]
98 #[should_panic(expected = "Browser lifetime was not initialized")]
99 fn reading_the_main_view_before_the_view_exists_fails() {
100 BrowserSingleViewLifetime::new().main_view();
101 }
102
103 #[test]
104 #[should_panic(expected = "Browser lifetime was not initialized")]
105 fn setting_the_main_view_before_the_view_exists_fails() {
106 BrowserSingleViewLifetime::new().set_main_view(None);
107 }
108}