@@ -56,6 +56,7 @@ pub struct Runtime<G> {
5656 pub ( super ) deferred_components : DeferredComponents ,
5757 pub ( super ) global_event_handler : G ,
5858 pub ( super ) function_table : FunctionTable ,
59+ pub ( super ) hot_reload : bool ,
5960}
6061
6162impl Runtime < ( ) > {
@@ -89,6 +90,7 @@ impl<G: GlobalEventHandler> Runtime<G> {
8990 fps : u32 ,
9091 global_event_handler : G ,
9192 function_table : FunctionTable ,
93+ hot_reload : bool ,
9294 ) -> Self {
9395 let sleep_micros: u64 = ( ( 1.0 / fps as f64 ) * 1000.0 * 1000.0 ) as u64 ;
9496
@@ -113,6 +115,7 @@ impl<G: GlobalEventHandler> Runtime<G> {
113115 sleep_micros,
114116 global_event_handler,
115117 function_table,
118+ hot_reload,
116119 }
117120 }
118121
@@ -133,39 +136,81 @@ impl<G: GlobalEventHandler> Runtime<G> {
133136
134137 pub fn run < B : Backend > ( & mut self , backend : & mut B ) -> Result < ( ) > {
135138 let sleep_micros = self . sleep_micros ;
136- self . with_frame ( backend, |backend, mut frame| {
137- // Perform the initial tick so tab index has a tree to work with.
138- // This means we can not react to any events in this tick as the tree does not
139- // yet have any widgets or components.
140- frame. tick ( backend) ?;
141139
142- let mut tabindex = TabIndex :: new ( & mut frame. tabindex , frame. tree . view ( ) ) ;
143- tabindex. next ( ) ;
140+ loop {
141+ let res = self . with_frame ( backend, |backend, mut frame| {
142+ // Perform the initial tick so tab index has a tree to work with.
143+ // This means we can not react to any events in this tick as the tree does not
144+ // yet have any widgets or components.
145+ _ = frame. tick ( backend) ;
146+ TabIndex :: new ( & mut frame. tabindex , frame. tree . view ( ) ) . next ( ) ;
147+
148+ if let Some ( current) = frame. tabindex . as_ref ( ) {
149+ frame. with_component ( current. widget_id , current. state_id , |comp, children, ctx| {
150+ comp. dyn_component . any_focus ( children, ctx)
151+ } ) ;
152+ }
144153
145- if let Some ( current) = frame. tabindex . as_ref ( ) {
146- frame. with_component ( current. widget_id , current. state_id , |comp, children, ctx| {
147- comp. dyn_component . any_focus ( children, ctx)
148- } ) ;
149- }
154+ loop {
155+ if REBUILD . swap ( false , Ordering :: Relaxed ) {
156+ frame. force_unmount_return ( ) ;
157+ backend. clear ( ) ;
158+ break Err ( Error :: Reload ) ;
159+ }
150160
151- loop {
152- frame. tick ( backend) ?;
153- if frame. layout_ctx . stop_runtime {
154- return Err ( Error :: Stop ) ;
155- }
161+ match frame. tick ( backend) {
162+ Ok ( _duration) => ( ) ,
163+ Err ( err) => match err {
164+ err @ ( Error :: Template ( _) | Error :: Widget ( _) ) => {
165+ match show_error ( err, backend, frame. document ) {
166+ Err ( Error :: Stop ) => return Err ( Error :: Stop ) ,
167+ // NOTE: we continue here as this should
168+ // cause the REBUILD to trigger
169+ Err ( Error :: Reload ) => continue ,
170+ _ => unreachable ! ( "show_error only return stop or rebuild" ) ,
171+ }
172+ }
173+ err => return Err ( err) ,
174+ } ,
175+ }
156176
157- frame. present ( backend ) ;
158- frame . cleanup ( ) ;
159- std :: thread :: sleep ( Duration :: from_micros ( sleep_micros ) ) ;
177+ if frame. layout_ctx . stop_runtime {
178+ return Err ( Error :: Stop ) ;
179+ }
160180
161- if REBUILD . swap ( false , Ordering :: Relaxed ) {
162- frame. force_rebuild ( ) ?;
163- backend. clear ( ) ;
164- break Ok ( ( ) ) ;
181+ frame. present ( backend) ;
182+ frame. cleanup ( ) ;
183+ std:: thread:: sleep ( Duration :: from_micros ( sleep_micros) ) ;
165184 }
185+ } ) ;
186+
187+ match res {
188+ Ok ( ( ) ) => panic ! ( ) ,
189+ Err ( e) => match e {
190+ Error :: Template ( _) | Error :: Widget ( _) => {
191+ unreachable ! ( "these error variants are handled inside the tick loop" )
192+ }
193+ Error :: Stop => return Err ( Error :: Stop ) ,
194+
195+ Error :: Reload => loop {
196+ // Reload can fail if the template fails to parse.
197+ match self . reload ( ) {
198+ Ok ( ( ) ) => break ,
199+ Err ( e) => {
200+ if let Err ( Error :: Stop ) = show_error ( e, backend, & self . document ) {
201+ return Err ( Error :: Stop ) ;
202+ }
203+ }
204+ }
205+ } ,
206+ e => return Err ( e) ,
207+ } ,
166208 }
167- } ) ?;
168209
210+ if !self . hot_reload {
211+ break ;
212+ }
213+ }
169214 Ok ( ( ) )
170215 }
171216
@@ -250,7 +295,8 @@ pub struct Frame<'rt, 'bp, G> {
250295}
251296
252297impl < ' rt , ' bp , G : GlobalEventHandler > Frame < ' rt , ' bp , G > {
253- pub fn force_rebuild ( mut self ) -> Result < ( ) > {
298+ /// Unmount all components and return them to storage
299+ pub fn force_unmount_return ( mut self ) {
254300 // call unmount on all components
255301 for i in 0 ..self . layout_ctx . components . len ( ) {
256302 let Some ( ( widget_id, state_id) ) = self . layout_ctx . components . get_ticking ( i) else { continue } ;
@@ -259,7 +305,6 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
259305 }
260306
261307 self . return_state_and_component ( ) ;
262- Ok ( ( ) )
263308 }
264309
265310 pub fn handle_global_event ( & mut self , event : Event ) -> Option < Event > {
@@ -714,11 +759,6 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
714759 }
715760 }
716761
717- // fn display_error(&mut self, backend: &mut impl Backend) {
718- // let _tpl = "text 'you goofed up'";
719- // backend.render(self.layout_ctx.glyph_map);
720- // }
721-
722762 fn post_cycle_events ( & mut self ) {
723763 while let Some ( event) = self . post_cycle_events . pop_front ( ) {
724764 self . event ( event) ;
0 commit comments