@@ -61,6 +61,40 @@ pub struct AppConfig {
6161 pub watcher_change : bool ,
6262 #[ serde( skip) ]
6363 pub config_change : bool ,
64+ #[ serde( skip) ]
65+ pub obj_change : bool ,
66+ }
67+
68+ impl AppConfig {
69+ pub fn set_project_dir ( & mut self , path : PathBuf ) {
70+ self . project_dir = Some ( path) ;
71+ self . target_obj_dir = None ;
72+ self . base_obj_dir = None ;
73+ self . obj_path = None ;
74+ self . build_target = false ;
75+ self . units . clear ( ) ;
76+ self . unit_nodes . clear ( ) ;
77+ self . watcher_change = true ;
78+ self . config_change = true ;
79+ self . obj_change = true ;
80+ }
81+
82+ pub fn set_target_obj_dir ( & mut self , path : PathBuf ) {
83+ self . target_obj_dir = Some ( path) ;
84+ self . obj_path = None ;
85+ self . obj_change = true ;
86+ }
87+
88+ pub fn set_base_obj_dir ( & mut self , path : PathBuf ) {
89+ self . base_obj_dir = Some ( path) ;
90+ self . obj_path = None ;
91+ self . obj_change = true ;
92+ }
93+
94+ pub fn set_obj_path ( & mut self , path : String ) {
95+ self . obj_path = Some ( path) ;
96+ self . obj_change = true ;
97+ }
6498}
6599
66100#[ derive( Default ) ]
@@ -109,6 +143,125 @@ impl App {
109143 app. relaunch_path = relaunch_path;
110144 app
111145 }
146+
147+ fn pre_update ( & mut self ) {
148+ let ViewState { jobs, diff_state, config_state, .. } = & mut self . view_state ;
149+
150+ for ( job, result) in jobs. iter_finished ( ) {
151+ match result {
152+ Ok ( result) => {
153+ log:: info!( "Job {} finished" , job. id) ;
154+ match result {
155+ JobResult :: None => {
156+ if let Some ( err) = & job. status . read ( ) . unwrap ( ) . error {
157+ log:: error!( "{:?}" , err) ;
158+ }
159+ }
160+ JobResult :: ObjDiff ( state) => {
161+ diff_state. build = Some ( state) ;
162+ }
163+ JobResult :: CheckUpdate ( state) => {
164+ config_state. check_update = Some ( state) ;
165+ }
166+ JobResult :: Update ( state) => {
167+ if let Ok ( mut guard) = self . relaunch_path . lock ( ) {
168+ * guard = Some ( state. exe_path ) ;
169+ }
170+ self . should_relaunch = true ;
171+ }
172+ }
173+ }
174+ Err ( err) => {
175+ let err = if let Some ( msg) = err. downcast_ref :: < & ' static str > ( ) {
176+ anyhow:: Error :: msg ( * msg)
177+ } else if let Some ( msg) = err. downcast_ref :: < String > ( ) {
178+ anyhow:: Error :: msg ( msg. clone ( ) )
179+ } else {
180+ anyhow:: Error :: msg ( "Thread panicked" )
181+ } ;
182+ let result = job. status . write ( ) ;
183+ if let Ok ( mut guard) = result {
184+ guard. error = Some ( err) ;
185+ } else {
186+ drop ( result) ;
187+ job. status = Arc :: new ( RwLock :: new ( JobStatus {
188+ title : "Error" . to_string ( ) ,
189+ progress_percent : 0.0 ,
190+ progress_items : None ,
191+ status : "" . to_string ( ) ,
192+ error : Some ( err) ,
193+ } ) ) ;
194+ }
195+ }
196+ }
197+ }
198+ jobs. clear_finished ( ) ;
199+ }
200+
201+ fn post_update ( & mut self ) {
202+ let ViewState { jobs, diff_state, config_state, .. } = & mut self . view_state ;
203+ let Ok ( mut config) = self . config . write ( ) else {
204+ return ;
205+ } ;
206+ let config = & mut * config;
207+
208+ if self . config_modified . swap ( false , Ordering :: Relaxed ) {
209+ config. config_change = true ;
210+ }
211+
212+ if config. config_change {
213+ config. config_change = false ;
214+ match load_project_config ( config) {
215+ Ok ( ( ) ) => config_state. load_error = None ,
216+ Err ( e) => {
217+ log:: error!( "Failed to load project config: {e}" ) ;
218+ config_state. load_error = Some ( format ! ( "{e}" ) ) ;
219+ }
220+ }
221+ }
222+
223+ if config. watcher_change {
224+ drop ( self . watcher . take ( ) ) ;
225+
226+ if let Some ( project_dir) = & config. project_dir {
227+ if !config. watch_patterns . is_empty ( ) {
228+ match build_globset ( & config. watch_patterns )
229+ . map_err ( anyhow:: Error :: new)
230+ . and_then ( |globset| {
231+ create_watcher (
232+ self . modified . clone ( ) ,
233+ self . config_modified . clone ( ) ,
234+ project_dir,
235+ globset,
236+ )
237+ . map_err ( anyhow:: Error :: new)
238+ } ) {
239+ Ok ( watcher) => self . watcher = Some ( watcher) ,
240+ Err ( e) => log:: error!( "Failed to create watcher: {e}" ) ,
241+ }
242+ }
243+ config. watcher_change = false ;
244+ }
245+ }
246+
247+ if config. obj_path . is_some ( )
248+ && self . modified . swap ( false , Ordering :: Relaxed )
249+ && !jobs. is_running ( Job :: ObjDiff )
250+ {
251+ jobs. push ( start_build ( self . config . clone ( ) ) ) ;
252+ }
253+
254+ if config. obj_change {
255+ * diff_state = Default :: default ( ) ;
256+ jobs. push ( start_build ( self . config . clone ( ) ) ) ;
257+ config. obj_change = false ;
258+ }
259+
260+ if config_state. queue_update_check {
261+ jobs. push ( start_check_update ( ) ) ;
262+ config_state. queue_update_check = false ;
263+ }
264+ }
112265}
113266
114267impl eframe:: App for App {
@@ -120,6 +273,8 @@ impl eframe::App for App {
120273 return ;
121274 }
122275
276+ self . pre_update ( ) ;
277+
123278 let Self { config, appearance, view_state, .. } = self ;
124279 ctx. set_style ( appearance. apply ( ctx. style ( ) . as_ref ( ) ) ) ;
125280
@@ -138,6 +293,7 @@ impl eframe::App for App {
138293 ui. menu_button ( "File" , |ui| {
139294 if ui. button ( "Appearance…" ) . clicked ( ) {
140295 * show_appearance_config = !* show_appearance_config;
296+ ui. close_menu ( ) ;
141297 }
142298 if ui. button ( "Quit" ) . clicked ( ) {
143299 frame. close ( ) ;
@@ -146,6 +302,7 @@ impl eframe::App for App {
146302 ui. menu_button ( "Tools" , |ui| {
147303 if ui. button ( "Demangle…" ) . clicked ( ) {
148304 * show_demangle = !* show_demangle;
305+ ui. close_menu ( ) ;
149306 }
150307 } ) ;
151308 } ) ;
@@ -169,8 +326,10 @@ impl eframe::App for App {
169326 } ) ;
170327 } else {
171328 egui:: SidePanel :: left ( "side_panel" ) . show ( ctx, |ui| {
172- config_ui ( ui, config, jobs, show_project_config, config_state, appearance) ;
173- jobs_ui ( ui, jobs, appearance) ;
329+ egui:: ScrollArea :: both ( ) . show ( ui, |ui| {
330+ config_ui ( ui, config, jobs, show_project_config, config_state, appearance) ;
331+ jobs_ui ( ui, jobs, appearance) ;
332+ } ) ;
174333 } ) ;
175334
176335 egui:: CentralPanel :: default ( ) . show ( ctx, |ui| {
@@ -182,9 +341,11 @@ impl eframe::App for App {
182341 appearance_window ( ctx, show_appearance_config, appearance) ;
183342 demangle_window ( ctx, show_demangle, demangle_state, appearance) ;
184343
344+ self . post_update ( ) ;
345+
185346 // Windows + request_repaint_after breaks dialogs:
186347 // https://github.com/emilk/egui/issues/2003
187- if cfg ! ( windows) || jobs. any_running ( ) {
348+ if cfg ! ( windows) || self . view_state . jobs . any_running ( ) {
188349 ctx. request_repaint ( ) ;
189350 } else {
190351 ctx. request_repaint_after ( Duration :: from_millis ( 100 ) ) ;
@@ -198,115 +359,6 @@ impl eframe::App for App {
198359 }
199360 eframe:: set_value ( storage, APPEARANCE_KEY , & self . appearance ) ;
200361 }
201-
202- fn post_rendering ( & mut self , _window_size_px : [ u32 ; 2 ] , _frame : & eframe:: Frame ) {
203- let ViewState { jobs, diff_state, config_state, .. } = & mut self . view_state ;
204-
205- for ( job, result) in jobs. iter_finished ( ) {
206- match result {
207- Ok ( result) => {
208- log:: info!( "Job {} finished" , job. id) ;
209- match result {
210- JobResult :: None => {
211- if let Some ( err) = & job. status . read ( ) . unwrap ( ) . error {
212- log:: error!( "{:?}" , err) ;
213- }
214- }
215- JobResult :: ObjDiff ( state) => {
216- diff_state. build = Some ( state) ;
217- }
218- JobResult :: CheckUpdate ( state) => {
219- config_state. check_update = Some ( state) ;
220- }
221- JobResult :: Update ( state) => {
222- if let Ok ( mut guard) = self . relaunch_path . lock ( ) {
223- * guard = Some ( state. exe_path ) ;
224- }
225- self . should_relaunch = true ;
226- }
227- }
228- }
229- Err ( err) => {
230- let err = if let Some ( msg) = err. downcast_ref :: < & ' static str > ( ) {
231- anyhow:: Error :: msg ( * msg)
232- } else if let Some ( msg) = err. downcast_ref :: < String > ( ) {
233- anyhow:: Error :: msg ( msg. clone ( ) )
234- } else {
235- anyhow:: Error :: msg ( "Thread panicked" )
236- } ;
237- let result = job. status . write ( ) ;
238- if let Ok ( mut guard) = result {
239- guard. error = Some ( err) ;
240- } else {
241- drop ( result) ;
242- job. status = Arc :: new ( RwLock :: new ( JobStatus {
243- title : "Error" . to_string ( ) ,
244- progress_percent : 0.0 ,
245- progress_items : None ,
246- status : "" . to_string ( ) ,
247- error : Some ( err) ,
248- } ) ) ;
249- }
250- }
251- }
252- }
253- jobs. clear_finished ( ) ;
254-
255- if let Ok ( mut config) = self . config . write ( ) {
256- let config = & mut * config;
257-
258- if self . config_modified . swap ( false , Ordering :: Relaxed ) {
259- config. config_change = true ;
260- }
261-
262- if config. config_change {
263- config. config_change = false ;
264- match load_project_config ( config) {
265- Ok ( ( ) ) => config_state. load_error = None ,
266- Err ( e) => {
267- log:: error!( "Failed to load project config: {e}" ) ;
268- config_state. load_error = Some ( format ! ( "{e}" ) ) ;
269- }
270- }
271- }
272-
273- if config. watcher_change {
274- drop ( self . watcher . take ( ) ) ;
275-
276- if let Some ( project_dir) = & config. project_dir {
277- if !config. watch_patterns . is_empty ( ) {
278- match build_globset ( & config. watch_patterns )
279- . map_err ( anyhow:: Error :: new)
280- . and_then ( |globset| {
281- create_watcher (
282- self . modified . clone ( ) ,
283- self . config_modified . clone ( ) ,
284- project_dir,
285- globset,
286- )
287- . map_err ( anyhow:: Error :: new)
288- } ) {
289- Ok ( watcher) => self . watcher = Some ( watcher) ,
290- Err ( e) => log:: error!( "Failed to create watcher: {e}" ) ,
291- }
292- }
293- config. watcher_change = false ;
294- }
295- }
296-
297- if config. obj_path . is_some ( )
298- && self . modified . swap ( false , Ordering :: Relaxed )
299- && !jobs. is_running ( Job :: ObjDiff )
300- {
301- jobs. push ( start_build ( self . config . clone ( ) ) ) ;
302- }
303-
304- if config_state. queue_update_check {
305- jobs. push ( start_check_update ( ) ) ;
306- config_state. queue_update_check = false ;
307- }
308- }
309- }
310362}
311363
312364fn create_watcher (
0 commit comments