1
- use std:: { collections:: BTreeMap , ffi:: CString } ;
1
+ use std:: { collections:: BTreeMap , ffi:: CString , os :: raw :: c_void } ;
2
2
3
3
use crate :: {
4
4
Error :: { Error_type , Result_type } ,
@@ -11,6 +11,9 @@ use File_system::{Mode_type, Type_type};
11
11
use Graphics :: { Color_type , Event_code_type , Point_type , Window_type , LVGL } ;
12
12
use Virtual_file_system :: Directory_type ;
13
13
14
+ pub const Windows_parent_child_changed : Graphics :: Event_code_type =
15
+ Graphics :: Event_code_type :: Custom_2 ;
16
+
14
17
pub struct Desk_type {
15
18
Window : Window_type ,
16
19
Tile_view : * mut LVGL :: lv_obj_t ,
@@ -21,6 +24,30 @@ pub struct Desk_type {
21
24
Shortcuts : BTreeMap < * mut LVGL :: lv_obj_t , String > ,
22
25
}
23
26
27
+ unsafe extern "C" fn Event_handler ( Event : * mut LVGL :: lv_event_t ) {
28
+ let Code = Event_code_type :: From_LVGL_code ( LVGL :: lv_event_get_code ( Event ) ) ;
29
+
30
+ if Code == Event_code_type :: Child_created || Code == Event_code_type :: Child_deleted {
31
+ let Target = LVGL :: lv_event_get_target ( Event ) as * mut LVGL :: lv_obj_t ;
32
+ let Target_parent = LVGL :: lv_obj_get_parent ( Target ) ;
33
+
34
+ let Current_target = LVGL :: lv_event_get_current_target ( Event ) as * mut LVGL :: lv_obj_t ;
35
+
36
+ // If the event is not for the current target, ignore it (not the parent window)
37
+ if Target_parent != Current_target {
38
+ return ;
39
+ }
40
+
41
+ let Desk = LVGL :: lv_event_get_user_data ( Event ) as * mut LVGL :: lv_obj_t ;
42
+
43
+ LVGL :: lv_obj_send_event (
44
+ Desk ,
45
+ Windows_parent_child_changed as u32 ,
46
+ Target as * mut c_void ,
47
+ ) ;
48
+ }
49
+ }
50
+
24
51
impl Drop for Desk_type {
25
52
fn drop ( & mut self ) {
26
53
unsafe {
@@ -45,15 +72,24 @@ impl Desk_type {
45
72
unsafe { LVGL :: lv_obj_has_flag ( self . Dock , LVGL :: lv_obj_flag_t_LV_OBJ_FLAG_HIDDEN) }
46
73
}
47
74
48
- pub fn New ( ) -> Result_type < Self > {
75
+ pub fn New ( Windows_parent : * mut LVGL :: lv_obj_t ) -> Result_type < Self > {
49
76
// - Lock the graphics
50
77
let _Lock = Graphics :: Get_instance ( ) . Lock ( ) ?; // Lock the graphics
51
78
52
79
// - Create a window
53
- let Window = Graphics :: Get_instance ( ) . Create_window ( ) ?;
80
+ let mut Window = Graphics :: Get_instance ( ) . Create_window ( ) ?;
81
+
82
+ Window . Set_icon ( "De" , Color_type :: Black ) ;
54
83
55
84
unsafe {
56
85
LVGL :: lv_obj_set_style_pad_all ( Window . Get_object ( ) , 0 , LVGL :: LV_STATE_DEFAULT ) ;
86
+
87
+ LVGL :: lv_obj_add_event_cb (
88
+ Windows_parent ,
89
+ Some ( Event_handler ) ,
90
+ Event_code_type :: All as u32 ,
91
+ Window . Get_object ( ) as * mut core:: ffi:: c_void ,
92
+ ) ;
57
93
}
58
94
59
95
// - Create the logo
@@ -144,30 +180,26 @@ impl Desk_type {
144
180
// - Create the main button
145
181
let Main_button = unsafe { Create_logo ( Dock , 1 , Color_type :: White ) ? } ;
146
182
147
- // Create some fake icons
148
- // for i in 0..5 {
149
- // unsafe {
150
- // Create_icon(Dock, &format!("Icon {}", i), Self::Dock_icon_size)?;
151
- // }
152
- // }
153
-
154
183
let Shortcuts = BTreeMap :: new ( ) ;
155
184
156
- Ok ( Self {
185
+ let Desk = Self {
157
186
Window ,
187
+ Tile_view ,
158
188
Desk_tile ,
159
189
Drawer_tile ,
160
- Tile_view ,
161
190
Dock ,
162
191
Main_button ,
163
192
Shortcuts ,
164
- } )
193
+ } ;
194
+
195
+ Ok ( Desk )
165
196
}
166
197
167
198
unsafe fn Create_drawer_shortcut (
168
199
& mut self ,
169
200
Entry_name : & str ,
170
201
Name : & str ,
202
+ Icon_color : Color_type ,
171
203
Icon_string : & str ,
172
204
Drawer : * mut LVGL :: lv_obj_t ,
173
205
) -> Result_type < ( ) > {
@@ -186,7 +218,7 @@ impl Desk_type {
186
218
LVGL :: lv_flex_align_t_LV_FLEX_ALIGN_CENTER,
187
219
) ;
188
220
189
- let Icon = Create_icon ( Container , Name , Icon_string , Self :: Drawer_icon_size ) ?;
221
+ let Icon = Create_icon ( Container , Icon_color , Icon_string , Self :: Drawer_icon_size ) ?;
190
222
191
223
let Label = LVGL :: lv_label_create ( Container ) ;
192
224
@@ -217,8 +249,6 @@ impl Desk_type {
217
249
. map_err ( Error_type :: Failed_to_read_shortcut_directory ) ?;
218
250
219
251
for Shortcut_entry in Shortcuts_directory {
220
- println ! ( "Shortcut: {}" , Shortcut_entry . Get_name ( ) ) ;
221
-
222
252
if Shortcut_entry . Get_type ( ) != Type_type :: File {
223
253
continue ;
224
254
}
@@ -232,13 +262,13 @@ impl Desk_type {
232
262
self . Create_drawer_shortcut (
233
263
Shortcut_entry . Get_name ( ) ,
234
264
Shortcut . Get_name ( ) ,
265
+ Shortcut . Get_icon_color ( ) ,
235
266
Shortcut . Get_icon_string ( ) ,
236
267
Drawer ,
237
268
) ?;
238
269
}
239
- Err ( Error ) => {
270
+ Err ( _ ) => {
240
271
// ? : Log error ?
241
- println ! ( "Failed to read shortcut. {}" , Error ) ;
242
272
continue ;
243
273
}
244
274
}
@@ -284,12 +314,81 @@ impl Desk_type {
284
314
Ok ( ( ) )
285
315
}
286
316
317
+ fn Refresh_dock ( & self ) -> Result_type < ( ) > {
318
+ let Dock_child_count = unsafe { LVGL :: lv_obj_get_child_count ( self . Dock ) } ;
319
+
320
+ let Graphics_manager = Graphics :: Get_instance ( ) ;
321
+
322
+ let Window_count = Graphics_manager . Get_window_count ( ) ?;
323
+
324
+ // Remove the icons of the windows that are not in the dock
325
+ for i in 1 ..Dock_child_count {
326
+ let Icon = unsafe { LVGL :: lv_obj_get_child ( self . Dock , i as i32 ) } ;
327
+
328
+ if Icon == self . Main_button {
329
+ continue ;
330
+ }
331
+
332
+ let Dock_window_identifier = unsafe { LVGL :: lv_obj_get_user_data ( Icon ) as usize } ;
333
+
334
+ let Found = ( 1 ..Window_count ) . find ( |& i| {
335
+ if let Ok ( Window_identifier ) = Graphics_manager . Get_window_identifier ( i) {
336
+ Window_identifier == Dock_window_identifier
337
+ } else {
338
+ false
339
+ }
340
+ } ) ;
341
+
342
+ if Found . is_none ( ) {
343
+ unsafe {
344
+ LVGL :: lv_obj_delete ( Icon ) ;
345
+ }
346
+ }
347
+ }
348
+
349
+ // Add the new icons
350
+ for i in 1 ..Window_count {
351
+ let Window_identifier =
352
+ if let Ok ( Window_identifier ) = Graphics_manager . Get_window_identifier ( i) {
353
+ Window_identifier
354
+ } else {
355
+ continue ;
356
+ } ;
357
+
358
+ // Find the index of the window in the dock
359
+ let Found = ( 1 ..Dock_child_count ) . find ( |& i| {
360
+ let Dock_window_identifier = unsafe {
361
+ let Icon = LVGL :: lv_obj_get_child ( self . Dock , i as i32 ) ;
362
+
363
+ LVGL :: lv_obj_get_user_data ( Icon ) as usize
364
+ } ;
365
+
366
+ Dock_window_identifier == Window_identifier
367
+ } ) ;
368
+
369
+ // If the window is not in the dock, add it
370
+ if Found . is_none ( ) {
371
+ let ( Icon_string , Icon_color ) = Graphics_manager . Get_window_icon ( i) ?;
372
+
373
+ let Window_identifier = Graphics_manager . Get_window_identifier ( i) ?;
374
+
375
+ unsafe {
376
+ let Icon =
377
+ Create_icon ( self . Dock , Icon_color , & Icon_string , Self :: Dock_icon_size ) ?;
378
+
379
+ LVGL :: lv_obj_set_user_data ( Icon , Window_identifier as * mut c_void ) ;
380
+ }
381
+ }
382
+ }
383
+
384
+ Ok ( ( ) )
385
+ }
386
+
287
387
pub fn Event_handler ( & mut self ) {
388
+ let _Lock = Graphics :: Get_instance ( ) . Lock ( ) . unwrap ( ) ;
288
389
while let Some ( Event ) = self . Window . Pop_event ( ) {
289
390
match Event . Get_code ( ) {
290
391
Self :: Home_event => unsafe {
291
- let _Lock = Graphics :: Get_instance ( ) . Lock ( ) . unwrap ( ) ;
292
-
293
392
LVGL :: lv_tileview_set_tile_by_index (
294
393
self . Tile_view ,
295
394
0 ,
@@ -299,7 +398,6 @@ impl Desk_type {
299
398
} ,
300
399
Event_code_type :: Value_changed => {
301
400
if Event . Get_target ( ) == self . Tile_view {
302
- let _Lock = Graphics :: Get_instance ( ) . Lock ( ) . unwrap ( ) ;
303
401
unsafe {
304
402
if LVGL :: lv_tileview_get_tile_active ( self . Tile_view ) == self . Desk_tile {
305
403
LVGL :: lv_obj_clean ( self . Drawer_tile ) ;
@@ -310,16 +408,24 @@ impl Desk_type {
310
408
}
311
409
}
312
410
Event_code_type :: Clicked => {
313
- let _Lock = Graphics :: Get_instance ( ) . Lock ( ) . unwrap ( ) ;
314
-
411
+ // If the target is a shortcut, execute the shortcut
315
412
if let Some ( Shortcut_name ) = self . Shortcuts . get ( & Event . Get_target ( ) ) {
316
413
if let Err ( Error ) = self . Execute_shortcut ( Shortcut_name ) {
317
- println ! ( "Failed to execute shortcut. {}" , Error ) ;
414
+ // ? : Log error ?
415
+ todo ! ( "Failed to execute shortcut {}" , Error . to_string( ) ) ;
318
416
}
319
417
}
418
+ // If the target is a dock icon, move the window to the foreground
419
+ else if unsafe { LVGL :: lv_obj_get_parent ( Event . Get_target ( ) ) == self . Dock } {
420
+ let Window_identifier =
421
+ unsafe { LVGL :: lv_obj_get_user_data ( Event . Get_target ( ) ) as usize } ;
422
+
423
+ Graphics :: Get_instance ( )
424
+ . Maximize_window ( Window_identifier )
425
+ . unwrap ( ) ;
426
+ }
320
427
}
321
428
Event_code_type :: Pressed => {
322
- let _Lock = Graphics :: Get_instance ( ) . Lock ( ) . unwrap ( ) ;
323
429
if Event . Get_target ( ) == self . Main_button
324
430
|| unsafe {
325
431
LVGL :: lv_obj_get_parent ( Event . Get_target ( ) ) == self . Main_button
@@ -362,6 +468,16 @@ impl Desk_type {
362
468
}
363
469
}
364
470
}
471
+ Windows_parent_child_changed => {
472
+ // Ignore consecutive windows parent child changed events
473
+ if let Some ( Peeked_event ) = self . Window . Peek_event ( ) {
474
+ if Peeked_event . Get_code ( ) == Windows_parent_child_changed {
475
+ continue ;
476
+ }
477
+ }
478
+
479
+ self . Refresh_dock ( ) . unwrap ( ) ;
480
+ }
365
481
_ => { }
366
482
}
367
483
}
0 commit comments