@@ -11,8 +11,9 @@ use std::{
11
11
rc:: Rc ,
12
12
} ;
13
13
14
+ use accelerator:: to_gtk_mnemonic;
14
15
use dpi:: Position ;
15
- use gtk4:: { gio:: SimpleActionGroup , glib:: VariantTy , prelude:: * } ;
16
+ use gtk4:: { gio, glib:: VariantTy , prelude:: * } ;
16
17
pub ( crate ) use icon:: PlatformIcon ;
17
18
18
19
use crate :: {
@@ -24,27 +25,31 @@ use crate::{
24
25
25
26
static COUNTER : Counter = Counter :: new ( ) ;
26
27
27
- struct GtkMenuBar ( gtk4:: PopoverMenuBar , gtk4:: gio:: Menu ) ;
28
+ const DEFAULT_ACTION : & str = "_internal_sendEvent" ;
29
+ const DEFAULT_ACTION_GROUP : & str = "muda" ;
30
+ const DEFAULT_DETAILED_ACTION : & str = "muda._internal_sendEvent" ;
31
+
32
+ struct GtkMenuBar ( gtk4:: PopoverMenuBar , gio:: Menu ) ;
28
33
29
34
impl GtkMenuBar {
30
35
fn new ( ) -> Self {
31
- let menu = gtk4 :: gio:: Menu :: new ( ) ;
36
+ let menu = gio:: Menu :: new ( ) ;
32
37
Self ( gtk4:: PopoverMenuBar :: from_model ( Some ( & menu) ) , menu)
33
38
}
34
39
35
40
fn widget ( & self ) -> & gtk4:: PopoverMenuBar {
36
41
& self . 0
37
42
}
38
43
39
- fn menu ( & self ) -> & gtk4 :: gio:: Menu {
44
+ fn menu ( & self ) -> & gio:: Menu {
40
45
& self . 1
41
46
}
42
47
}
43
48
44
49
pub struct Menu {
45
50
id : MenuId ,
46
51
instances : HashMap < u32 , GtkMenuBar > ,
47
- action_group : Option < SimpleActionGroup > ,
52
+ action_group : Option < gio :: SimpleActionGroup > ,
48
53
children : Vec < Rc < RefCell < MenuChild > > > ,
49
54
}
50
55
@@ -114,24 +119,15 @@ impl Menu {
114
119
if self . action_group . is_none ( ) {
115
120
let action_group = gtk4:: gio:: SimpleActionGroup :: new ( ) ;
116
121
117
- let action = gtk4:: gio:: SimpleAction :: new ( "sendEvent" , Some ( & VariantTy :: STRING ) ) ;
118
- action_group. add_action ( & action) ;
122
+ let action = gtk4:: gio:: SimpleAction :: new ( DEFAULT_ACTION , Some ( & VariantTy :: STRING ) ) ;
119
123
action. connect_activate ( |_, v| {
120
124
if let Some ( v) = v {
121
125
MenuEvent :: send ( MenuEvent {
122
126
id : MenuId ( v. as_ref ( ) . to_string ( ) ) ,
123
127
} ) ;
124
128
}
125
129
} ) ;
126
-
127
- let action =
128
- gtk4:: gio:: SimpleAction :: new_stateful ( "sendCheckEvent" , None , & "" . to_variant ( ) ) ;
129
130
action_group. add_action ( & action) ;
130
- action. connect_activate ( |_, _| {
131
- MenuEvent :: send ( MenuEvent {
132
- id : MenuId ( "0" . to_string ( ) ) ,
133
- } ) ;
134
- } ) ;
135
131
136
132
self . action_group = Some ( action_group) ;
137
133
}
@@ -144,7 +140,7 @@ impl Menu {
144
140
return Err ( crate :: Error :: AlreadyInitialized ) ;
145
141
}
146
142
147
- window. insert_action_group ( "muda" , self . action_group . as_ref ( ) ) ;
143
+ window. insert_action_group ( DEFAULT_ACTION_GROUP , self . action_group . as_ref ( ) ) ;
148
144
149
145
for item in self . items ( ) {
150
146
self . add_menu_item_with_id ( item. as_ref ( ) , id) ?;
@@ -221,11 +217,12 @@ impl Menu {
221
217
222
218
#[ derive( Clone ) ]
223
219
enum GtkChild {
224
- Item ( gtk4 :: gio:: MenuItem ) ,
220
+ Item ( gio:: MenuItem ) ,
225
221
Submenu {
226
222
id : u32 ,
227
- item : gtk4:: gio:: MenuItem ,
228
- menu : gtk4:: gio:: Menu ,
223
+ item : gio:: MenuItem ,
224
+ menu : gio:: Menu ,
225
+ action_group : Option < gio:: SimpleActionGroup > ,
229
226
} ,
230
227
}
231
228
@@ -239,14 +236,21 @@ impl GtkChild {
239
236
}
240
237
}
241
238
242
- fn menu ( & self ) -> & gtk4 :: gio:: Menu {
239
+ fn menu ( & self ) -> & gio:: Menu {
243
240
match self {
244
241
GtkChild :: Item ( _) => {
245
242
unreachable ! ( "This is a bug report to https://github.com/tauri-apps/muda" )
246
243
}
247
244
GtkChild :: Submenu { menu, .. } => menu,
248
245
}
249
246
}
247
+
248
+ fn action_group ( & self ) -> Option < & gio:: SimpleActionGroup > {
249
+ match self {
250
+ GtkChild :: Item ( _) => None ,
251
+ GtkChild :: Submenu { action_group, .. } => action_group. as_ref ( ) ,
252
+ }
253
+ }
250
254
}
251
255
252
256
pub struct MenuChild {
@@ -255,6 +259,8 @@ pub struct MenuChild {
255
259
enabled : bool ,
256
260
accelerator : Option < Accelerator > ,
257
261
262
+ checked : bool ,
263
+
258
264
type_ : MenuItemType ,
259
265
260
266
instances : HashMap < u32 , Vec < GtkChild > > ,
@@ -267,6 +273,7 @@ impl MenuChild {
267
273
id : id. unwrap_or_else ( || MenuId ( COUNTER . next ( ) . to_string ( ) ) ) ,
268
274
text : text. to_string ( ) ,
269
275
enabled,
276
+ checked : false ,
270
277
accelerator : None ,
271
278
type_ : MenuItemType :: Submenu ,
272
279
instances : HashMap :: new ( ) ,
@@ -277,17 +284,18 @@ impl MenuChild {
277
284
fn create_gtk_item_for_submenu (
278
285
& mut self ,
279
286
menu_id : u32 ,
280
- action_group : Option < & gtk4 :: gio:: SimpleActionGroup > ,
281
- ) -> crate :: Result < gtk4 :: gio:: MenuItem > {
282
- let menu = gtk4 :: gio:: Menu :: new ( ) ;
283
- let item = gtk4 :: gio:: MenuItem :: new_submenu ( Some ( & self . text ) , & menu) ;
287
+ action_group : Option < & gio:: SimpleActionGroup > ,
288
+ ) -> crate :: Result < gio:: MenuItem > {
289
+ let menu = gio:: Menu :: new ( ) ;
290
+ let item = gio:: MenuItem :: new_submenu ( Some ( & to_gtk_mnemonic ( & self . text ) ) , & menu) ;
284
291
285
292
let id = COUNTER . next ( ) ;
286
293
287
294
let child = GtkChild :: Submenu {
288
295
item : item. clone ( ) ,
289
296
menu,
290
297
id,
298
+ action_group : action_group. cloned ( ) ,
291
299
} ;
292
300
293
301
self . instances . entry ( menu_id) . or_default ( ) . push ( child) ;
@@ -307,7 +315,7 @@ impl MenuChild {
307
315
308
316
for menus in self . instances . values ( ) {
309
317
for gtk_child in menus {
310
- let gtk_item = item. make_gtk_menu_item ( gtk_child. id ( ) , None /* TODO */ ) ?;
318
+ let gtk_item = item. make_gtk_menu_item ( gtk_child. id ( ) , gtk_child . action_group ( ) ) ?;
311
319
312
320
match op {
313
321
AddOp :: Append => gtk_child. menu ( ) . append_item ( & gtk_item) ,
@@ -324,7 +332,7 @@ impl MenuChild {
324
332
pub fn add_menu_item_with_id ( & self , item : & dyn IsMenuItem , id : u32 ) -> crate :: Result < ( ) > {
325
333
for menus in self . instances . values ( ) {
326
334
for gtk_child in menus. iter ( ) . filter ( |m| m. id ( ) == id) {
327
- let gtk_item = item. make_gtk_menu_item ( gtk_child. id ( ) , None /* TODO */ ) ?;
335
+ let gtk_item = item. make_gtk_menu_item ( gtk_child. id ( ) , gtk_child . action_group ( ) ) ?;
328
336
gtk_child. menu ( ) . append_item ( & gtk_item) ;
329
337
}
330
338
}
@@ -364,6 +372,7 @@ impl MenuChild {
364
372
text : text. to_string ( ) ,
365
373
enabled,
366
374
accelerator,
375
+ checked : false ,
367
376
type_ : MenuItemType :: MenuItem ,
368
377
instances : HashMap :: new ( ) ,
369
378
children : Vec :: new ( ) ,
@@ -373,11 +382,11 @@ impl MenuChild {
373
382
fn create_gtk_item_for_menu_item (
374
383
& mut self ,
375
384
menu_id : u32 ,
376
- action_group : Option < & gtk4 :: gio:: SimpleActionGroup > ,
377
- ) -> crate :: Result < gtk4 :: gio:: MenuItem > {
378
- let item = gtk4 :: gio:: MenuItem :: new (
379
- Some ( & self . text ) ,
380
- Some ( & format ! ( "muda.sendEvent ::{}" , self . id. as_ref( ) ) ) ,
385
+ _action_group : Option < & gio:: SimpleActionGroup > ,
386
+ ) -> crate :: Result < gio:: MenuItem > {
387
+ let item = gio:: MenuItem :: new (
388
+ Some ( & to_gtk_mnemonic ( & self . text ) ) ,
389
+ Some ( & format ! ( "{DEFAULT_DETAILED_ACTION} ::{}" , self . id. as_ref( ) ) ) ,
381
390
) ;
382
391
383
392
let child = GtkChild :: Item ( item. clone ( ) ) ;
@@ -422,6 +431,7 @@ impl MenuChild {
422
431
text : text. unwrap_or_else ( || item_type. text ( ) . to_string ( ) ) ,
423
432
enabled : true ,
424
433
accelerator : None ,
434
+ checked : false ,
425
435
type_ : MenuItemType :: Predefined ,
426
436
instances : HashMap :: new ( ) ,
427
437
children : Vec :: new ( ) ,
@@ -442,12 +452,39 @@ impl MenuChild {
442
452
text : text. to_string ( ) ,
443
453
enabled,
444
454
accelerator,
455
+ checked,
445
456
type_ : MenuItemType :: Check ,
446
457
instances : HashMap :: new ( ) ,
447
458
children : Vec :: new ( ) ,
448
459
}
449
460
}
450
461
462
+ fn create_gtk_item_for_check_menu_item (
463
+ & mut self ,
464
+ menu_id : u32 ,
465
+ action_group : Option < & gio:: SimpleActionGroup > ,
466
+ ) -> crate :: Result < gio:: MenuItem > {
467
+ let item = gio:: MenuItem :: new (
468
+ Some ( & to_gtk_mnemonic ( & self . text ) ) ,
469
+ Some ( & format ! ( "{DEFAULT_ACTION_GROUP}.{}" , self . id. as_ref( ) ) ) ,
470
+ ) ;
471
+
472
+ if let Some ( action_group) = action_group {
473
+ let state = & self . checked . to_variant ( ) ;
474
+ let action = gio:: SimpleAction :: new_stateful ( self . id . as_ref ( ) , None , state) ;
475
+ let id = self . id . clone ( ) ;
476
+ action. connect_state_notify ( move |_| {
477
+ MenuEvent :: send ( MenuEvent { id : id. clone ( ) } ) ;
478
+ } ) ;
479
+ action_group. add_action ( & action) ;
480
+ }
481
+
482
+ let child = GtkChild :: Item ( item. clone ( ) ) ;
483
+ self . instances . entry ( menu_id) . or_default ( ) . push ( child) ;
484
+
485
+ Ok ( item)
486
+ }
487
+
451
488
pub fn is_checked ( & self ) -> bool {
452
489
todo ! ( )
453
490
}
@@ -470,6 +507,7 @@ impl MenuChild {
470
507
text : text. to_string ( ) ,
471
508
enabled,
472
509
accelerator,
510
+ checked : false ,
473
511
type_ : MenuItemType :: Icon ,
474
512
instances : HashMap :: new ( ) ,
475
513
children : Vec :: new ( ) ,
@@ -488,6 +526,7 @@ impl MenuChild {
488
526
text : text. to_string ( ) ,
489
527
enabled,
490
528
accelerator,
529
+ checked : false ,
491
530
type_ : MenuItemType :: Submenu ,
492
531
instances : HashMap :: new ( ) ,
493
532
children : Vec :: new ( ) ,
@@ -501,19 +540,17 @@ impl dyn IsMenuItem + '_ {
501
540
fn make_gtk_menu_item (
502
541
& self ,
503
542
menu_id : u32 ,
504
- action_group : Option < & gtk4 :: gio:: SimpleActionGroup > ,
505
- ) -> crate :: Result < gtk4 :: gio:: MenuItem > {
543
+ action_group : Option < & gio:: SimpleActionGroup > ,
544
+ ) -> crate :: Result < gio:: MenuItem > {
506
545
let kind = self . kind ( ) ;
507
546
let mut child = kind. child_mut ( ) ;
508
547
match child. item_type ( ) {
509
548
MenuItemType :: Submenu => child. create_gtk_item_for_submenu ( menu_id, action_group) ,
510
549
MenuItemType :: MenuItem => child. create_gtk_item_for_menu_item ( menu_id, action_group) ,
550
+ MenuItemType :: Check => child. create_gtk_item_for_check_menu_item ( menu_id, action_group) ,
511
551
_ => todo ! ( ) ,
512
552
// MenuItemType::Predefined => {
513
- // child.create_gtk_item_for_predefined_menu_item(menu_id, action_group, add_to_store)
514
- // }
515
- // MenuItemType::Check => {
516
- // child.create_gtk_item_for_check_menu_item(menu_id, action_group, add_to_store)
553
+ // child.create_gtk_item_for_predefined_menu_item(menu_id, action_group)
517
554
// }
518
555
// MenuItemType::Icon => child.create_gtk_item_for_icon_menu_item(
519
556
// menu_id,
0 commit comments