tilo_app/framework/
opening.rs1use std::cell::RefCell;
15
16use ui_core::application::ComponentReplacement;
17use ui_core::launch::LaunchError;
18use ui_core::record::RecordOpening;
19use ui_core::widget::{AppKind, AppWidget, IconDescriptor, Widget};
20
21use super::app::OpeningView;
22
23pub struct Opened(RefCell<Option<Box<dyn OpeningView>>>);
27
28impl Opened {
29 pub(crate) fn new(shown: Box<dyn OpeningView>) -> Self {
30 Self(RefCell::new(Some(shown)))
31 }
32
33 #[must_use]
35 pub fn take<W: 'static>(&self) -> Option<Box<W>> {
36 let shown = self.0.borrow_mut().take()?;
37 shown.into_lent().downcast::<W>().ok()
38 }
39}
40
41pub(crate) type Build =
43 Box<dyn FnOnce(Box<dyn OpeningView>) -> Result<ComponentReplacement, LaunchError>>;
44
45pub(crate) struct OpeningRoot {
47 shown: Box<dyn OpeningView>,
48 record: RecordOpening,
49 build: Option<Build>,
50 title: &'static str,
51 icon: IconDescriptor,
52}
53
54impl OpeningRoot {
55 pub(crate) fn new(
56 shown: Box<dyn OpeningView>,
57 record: RecordOpening,
58 build: Build,
59 (title, icon): (&'static str, IconDescriptor),
60 ) -> Self {
61 record.wake_when_decoded(ui_core::wake::WakeHandle::new());
63 Self {
64 shown,
65 record,
66 build: Some(build),
67 title,
68 icon,
69 }
70 }
71}
72
73impl ui_core::widget::Decorator for OpeningRoot {
74 type Inner = dyn Widget;
75
76 fn inner(&self) -> &(dyn Widget + 'static) {
77 &*self.shown
78 }
79
80 fn inner_mut(&mut self) -> &mut (dyn Widget + 'static) {
81 &mut *self.shown
82 }
83
84 fn provide<'a>(&'a self, _request: &mut ui_core::widget::capability::Request<'a, '_>) {}
87
88 fn provide_mut<'a>(
89 &'a mut self,
90 _request: &mut ui_core::widget::capability::RequestMut<'a, '_>,
91 ) {
92 }
93}
94
95impl AppWidget for OpeningRoot {
96 fn app_kind(&self) -> AppKind {
97 AppKind::Editor
98 }
99
100 fn app_title(&self) -> &str {
101 self.title
102 }
103
104 fn app_icon(&self) -> IconDescriptor {
105 self.icon.clone()
106 }
107
108 fn take_component_replacement(&mut self) -> Option<ComponentReplacement> {
111 self.build.as_ref()?;
112 match self.record.take_in(false) {
113 Ok(false) => return None,
114 Ok(true) => {}
115 Err(error) => tracing::warn!(%error, "the workspace's record did not open"),
116 }
117 let build = self.build.take()?;
118 let shown = std::mem::replace(&mut self.shown, Box::new(ui_core::widget::Absent::new()));
119 match build(shown) {
120 Ok(replacement) => Some(replacement),
121 Err(error) => {
122 tracing::error!(%error, "the workspace's record opened, and its window did not");
123 None
124 }
125 }
126 }
127}