@@ -61,6 +61,40 @@ pub struct AppConfig {
61
61
pub watcher_change : bool ,
62
62
#[ serde( skip) ]
63
63
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
+ }
64
98
}
65
99
66
100
#[ derive( Default ) ]
@@ -109,6 +143,125 @@ impl App {
109
143
app. relaunch_path = relaunch_path;
110
144
app
111
145
}
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
+ }
112
265
}
113
266
114
267
impl eframe:: App for App {
@@ -120,6 +273,8 @@ impl eframe::App for App {
120
273
return ;
121
274
}
122
275
276
+ self . pre_update ( ) ;
277
+
123
278
let Self { config, appearance, view_state, .. } = self ;
124
279
ctx. set_style ( appearance. apply ( ctx. style ( ) . as_ref ( ) ) ) ;
125
280
@@ -138,6 +293,7 @@ impl eframe::App for App {
138
293
ui. menu_button ( "File" , |ui| {
139
294
if ui. button ( "Appearance…" ) . clicked ( ) {
140
295
* show_appearance_config = !* show_appearance_config;
296
+ ui. close_menu ( ) ;
141
297
}
142
298
if ui. button ( "Quit" ) . clicked ( ) {
143
299
frame. close ( ) ;
@@ -146,6 +302,7 @@ impl eframe::App for App {
146
302
ui. menu_button ( "Tools" , |ui| {
147
303
if ui. button ( "Demangle…" ) . clicked ( ) {
148
304
* show_demangle = !* show_demangle;
305
+ ui. close_menu ( ) ;
149
306
}
150
307
} ) ;
151
308
} ) ;
@@ -169,8 +326,10 @@ impl eframe::App for App {
169
326
} ) ;
170
327
} else {
171
328
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
+ } ) ;
174
333
} ) ;
175
334
176
335
egui:: CentralPanel :: default ( ) . show ( ctx, |ui| {
@@ -182,9 +341,11 @@ impl eframe::App for App {
182
341
appearance_window ( ctx, show_appearance_config, appearance) ;
183
342
demangle_window ( ctx, show_demangle, demangle_state, appearance) ;
184
343
344
+ self . post_update ( ) ;
345
+
185
346
// Windows + request_repaint_after breaks dialogs:
186
347
// https://github.com/emilk/egui/issues/2003
187
- if cfg ! ( windows) || jobs. any_running ( ) {
348
+ if cfg ! ( windows) || self . view_state . jobs . any_running ( ) {
188
349
ctx. request_repaint ( ) ;
189
350
} else {
190
351
ctx. request_repaint_after ( Duration :: from_millis ( 100 ) ) ;
@@ -198,115 +359,6 @@ impl eframe::App for App {
198
359
}
199
360
eframe:: set_value ( storage, APPEARANCE_KEY , & self . appearance ) ;
200
361
}
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
- }
310
362
}
311
363
312
364
fn create_watcher (
0 commit comments