ranma 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,588 @@
1
+ use std::cell::RefCell;
2
+ use std::collections::HashMap;
3
+ use magnus::{function, method, prelude::*, Error, Ruby, Value, TryConvert};
4
+
5
+ thread_local! {
6
+ static MENUS: RefCell<HashMap<String, muda::Menu>> = RefCell::new(HashMap::new());
7
+ static SUBMENUS: RefCell<HashMap<String, muda::Submenu>> = RefCell::new(HashMap::new());
8
+ static MENU_ITEMS: RefCell<HashMap<String, muda::MenuItem>> = RefCell::new(HashMap::new());
9
+ static CHECK_MENU_ITEMS: RefCell<HashMap<String, muda::CheckMenuItem>> = RefCell::new(HashMap::new());
10
+ static PREDEFINED_ITEMS: RefCell<HashMap<String, muda::PredefinedMenuItem>> = RefCell::new(HashMap::new());
11
+ }
12
+
13
+ pub fn with_menu<F, R>(id: &str, f: F) -> Option<R>
14
+ where
15
+ F: FnOnce(&muda::Menu) -> R,
16
+ {
17
+ MENUS.with(|cell| {
18
+ let menus = cell.borrow();
19
+ menus.get(id).map(f)
20
+ })
21
+ }
22
+
23
+ pub fn clear_all() {
24
+ MENUS.with(|cell| cell.borrow_mut().clear());
25
+ SUBMENUS.with(|cell| cell.borrow_mut().clear());
26
+ MENU_ITEMS.with(|cell| cell.borrow_mut().clear());
27
+ CHECK_MENU_ITEMS.with(|cell| cell.borrow_mut().clear());
28
+ PREDEFINED_ITEMS.with(|cell| cell.borrow_mut().clear());
29
+ }
30
+
31
+ fn append_item_to_menu(menu: &muda::Menu, item: Value) -> Result<(), Error> {
32
+ let ruby = unsafe { Ruby::get_unchecked() };
33
+
34
+ if let Ok(submenu) = <&RbSubmenu>::try_convert(item) {
35
+ let id = submenu.menu_id.clone();
36
+ return SUBMENUS.with(|cell| {
37
+ let subs = cell.borrow();
38
+ if let Some(s) = subs.get(&id) {
39
+ menu.append(s).map_err(|e| {
40
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append submenu: {}", e))
41
+ })
42
+ } else {
43
+ Err(Error::new(ruby.exception_runtime_error(), "Submenu not found in registry"))
44
+ }
45
+ });
46
+ }
47
+ if let Ok(menu_item) = <&RbMenuItem>::try_convert(item) {
48
+ let id = menu_item.menu_id.clone();
49
+ return MENU_ITEMS.with(|cell| {
50
+ let items = cell.borrow();
51
+ if let Some(i) = items.get(&id) {
52
+ menu.append(i).map_err(|e| {
53
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append menu item: {}", e))
54
+ })
55
+ } else {
56
+ Err(Error::new(ruby.exception_runtime_error(), "MenuItem not found in registry"))
57
+ }
58
+ });
59
+ }
60
+ if let Ok(check_item) = <&RbCheckMenuItem>::try_convert(item) {
61
+ let id = check_item.menu_id.clone();
62
+ return CHECK_MENU_ITEMS.with(|cell| {
63
+ let items = cell.borrow();
64
+ if let Some(i) = items.get(&id) {
65
+ menu.append(i).map_err(|e| {
66
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append check menu item: {}", e))
67
+ })
68
+ } else {
69
+ Err(Error::new(ruby.exception_runtime_error(), "CheckMenuItem not found in registry"))
70
+ }
71
+ });
72
+ }
73
+ if let Ok(predefined) = <&RbPredefinedMenuItem>::try_convert(item) {
74
+ let id = predefined.menu_id.clone();
75
+ return PREDEFINED_ITEMS.with(|cell| {
76
+ let items = cell.borrow();
77
+ if let Some(i) = items.get(&id) {
78
+ menu.append(i).map_err(|e| {
79
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append predefined item: {}", e))
80
+ })
81
+ } else {
82
+ Err(Error::new(ruby.exception_runtime_error(), "PredefinedMenuItem not found in registry"))
83
+ }
84
+ });
85
+ }
86
+
87
+ Err(Error::new(ruby.exception_type_error(), "Expected Submenu, MenuItem, CheckMenuItem, or PredefinedMenuItem"))
88
+ }
89
+
90
+ fn append_item_to_submenu(submenu: &muda::Submenu, item: Value) -> Result<(), Error> {
91
+ let ruby = unsafe { Ruby::get_unchecked() };
92
+
93
+ if let Ok(sub) = <&RbSubmenu>::try_convert(item) {
94
+ let id = sub.menu_id.clone();
95
+ return SUBMENUS.with(|cell| {
96
+ let subs = cell.borrow();
97
+ if let Some(s) = subs.get(&id) {
98
+ submenu.append(s).map_err(|e| {
99
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append submenu: {}", e))
100
+ })
101
+ } else {
102
+ Err(Error::new(ruby.exception_runtime_error(), "Submenu not found in registry"))
103
+ }
104
+ });
105
+ }
106
+ if let Ok(menu_item) = <&RbMenuItem>::try_convert(item) {
107
+ let id = menu_item.menu_id.clone();
108
+ return MENU_ITEMS.with(|cell| {
109
+ let items = cell.borrow();
110
+ if let Some(i) = items.get(&id) {
111
+ submenu.append(i).map_err(|e| {
112
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append menu item: {}", e))
113
+ })
114
+ } else {
115
+ Err(Error::new(ruby.exception_runtime_error(), "MenuItem not found in registry"))
116
+ }
117
+ });
118
+ }
119
+ if let Ok(check_item) = <&RbCheckMenuItem>::try_convert(item) {
120
+ let id = check_item.menu_id.clone();
121
+ return CHECK_MENU_ITEMS.with(|cell| {
122
+ let items = cell.borrow();
123
+ if let Some(i) = items.get(&id) {
124
+ submenu.append(i).map_err(|e| {
125
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append check menu item: {}", e))
126
+ })
127
+ } else {
128
+ Err(Error::new(ruby.exception_runtime_error(), "CheckMenuItem not found in registry"))
129
+ }
130
+ });
131
+ }
132
+ if let Ok(predefined) = <&RbPredefinedMenuItem>::try_convert(item) {
133
+ let id = predefined.menu_id.clone();
134
+ return PREDEFINED_ITEMS.with(|cell| {
135
+ let items = cell.borrow();
136
+ if let Some(i) = items.get(&id) {
137
+ submenu.append(i).map_err(|e| {
138
+ Error::new(ruby.exception_runtime_error(), format!("Failed to append predefined item: {}", e))
139
+ })
140
+ } else {
141
+ Err(Error::new(ruby.exception_runtime_error(), "PredefinedMenuItem not found in registry"))
142
+ }
143
+ });
144
+ }
145
+
146
+ Err(Error::new(ruby.exception_type_error(), "Expected Submenu, MenuItem, CheckMenuItem, or PredefinedMenuItem"))
147
+ }
148
+
149
+ // --- Menu ---
150
+
151
+ #[magnus::wrap(class = "Ranma::Menu", free_immediately, size)]
152
+ pub struct RbMenu {
153
+ menu_id: String,
154
+ }
155
+
156
+ impl RbMenu {
157
+ fn new() -> Self {
158
+ let menu = muda::Menu::new();
159
+ let id = menu.id().0.clone();
160
+ MENUS.with(|cell| {
161
+ cell.borrow_mut().insert(id.clone(), menu);
162
+ });
163
+ RbMenu { menu_id: id }
164
+ }
165
+
166
+ fn append(&self, item: Value) -> Result<(), Error> {
167
+ let ruby = unsafe { Ruby::get_unchecked() };
168
+ MENUS.with(|cell| {
169
+ let menus = cell.borrow();
170
+ if let Some(menu) = menus.get(&self.menu_id) {
171
+ append_item_to_menu(menu, item)
172
+ } else {
173
+ Err(Error::new(ruby.exception_runtime_error(), "Menu not found in registry"))
174
+ }
175
+ })
176
+ }
177
+
178
+ fn init_for_nsapp(&self) -> Result<(), Error> {
179
+ let ruby = unsafe { Ruby::get_unchecked() };
180
+ MENUS.with(|cell| {
181
+ let menus = cell.borrow();
182
+ if let Some(menu) = menus.get(&self.menu_id) {
183
+ menu.init_for_nsapp();
184
+ Ok(())
185
+ } else {
186
+ Err(Error::new(ruby.exception_runtime_error(), "Menu not found in registry"))
187
+ }
188
+ })
189
+ }
190
+
191
+ fn id(&self) -> String {
192
+ self.menu_id.clone()
193
+ }
194
+
195
+ fn inspect(&self) -> String {
196
+ format!("#<Ranma::Menu id={}>", self.menu_id)
197
+ }
198
+ }
199
+
200
+ // --- Submenu ---
201
+
202
+ #[magnus::wrap(class = "Ranma::Submenu", free_immediately, size)]
203
+ pub struct RbSubmenu {
204
+ menu_id: String,
205
+ }
206
+
207
+ impl RbSubmenu {
208
+ fn new(text: String, enabled: bool) -> Self {
209
+ let submenu = muda::Submenu::new(&text, enabled);
210
+ let id = submenu.id().0.clone();
211
+ SUBMENUS.with(|cell| {
212
+ cell.borrow_mut().insert(id.clone(), submenu);
213
+ });
214
+ RbSubmenu { menu_id: id }
215
+ }
216
+
217
+ fn append(&self, item: Value) -> Result<(), Error> {
218
+ let ruby = unsafe { Ruby::get_unchecked() };
219
+ SUBMENUS.with(|cell| {
220
+ let subs = cell.borrow();
221
+ if let Some(submenu) = subs.get(&self.menu_id) {
222
+ append_item_to_submenu(submenu, item)
223
+ } else {
224
+ Err(Error::new(ruby.exception_runtime_error(), "Submenu not found in registry"))
225
+ }
226
+ })
227
+ }
228
+
229
+ fn text(&self) -> String {
230
+ SUBMENUS.with(|cell| {
231
+ let subs = cell.borrow();
232
+ subs.get(&self.menu_id).map(|s| s.text()).unwrap_or_default()
233
+ })
234
+ }
235
+
236
+ fn set_text(&self, text: String) {
237
+ SUBMENUS.with(|cell| {
238
+ let subs = cell.borrow();
239
+ if let Some(s) = subs.get(&self.menu_id) {
240
+ s.set_text(&text);
241
+ }
242
+ });
243
+ }
244
+
245
+ fn is_enabled(&self) -> bool {
246
+ SUBMENUS.with(|cell| {
247
+ let subs = cell.borrow();
248
+ subs.get(&self.menu_id).map(|s| s.is_enabled()).unwrap_or(false)
249
+ })
250
+ }
251
+
252
+ fn set_enabled(&self, enabled: bool) {
253
+ SUBMENUS.with(|cell| {
254
+ let subs = cell.borrow();
255
+ if let Some(s) = subs.get(&self.menu_id) {
256
+ s.set_enabled(enabled);
257
+ }
258
+ });
259
+ }
260
+
261
+ fn set_as_windows_menu_for_nsapp(&self) {
262
+ SUBMENUS.with(|cell| {
263
+ let subs = cell.borrow();
264
+ if let Some(s) = subs.get(&self.menu_id) {
265
+ s.set_as_windows_menu_for_nsapp();
266
+ }
267
+ });
268
+ }
269
+
270
+ fn id(&self) -> String {
271
+ self.menu_id.clone()
272
+ }
273
+
274
+ fn inspect(&self) -> String {
275
+ let text = self.text();
276
+ format!("#<Ranma::Submenu id={} text={:?}>", self.menu_id, text)
277
+ }
278
+ }
279
+
280
+ // --- MenuItem ---
281
+
282
+ #[magnus::wrap(class = "Ranma::MenuItem", free_immediately, size)]
283
+ pub struct RbMenuItem {
284
+ menu_id: String,
285
+ }
286
+
287
+ impl RbMenuItem {
288
+ fn new(text: String, enabled: bool) -> Self {
289
+ let item = muda::MenuItem::new(&text, enabled, None);
290
+ let id = item.id().0.clone();
291
+ MENU_ITEMS.with(|cell| {
292
+ cell.borrow_mut().insert(id.clone(), item);
293
+ });
294
+ RbMenuItem { menu_id: id }
295
+ }
296
+
297
+ fn text(&self) -> String {
298
+ MENU_ITEMS.with(|cell| {
299
+ let items = cell.borrow();
300
+ items.get(&self.menu_id).map(|i| i.text()).unwrap_or_default()
301
+ })
302
+ }
303
+
304
+ fn set_text(&self, text: String) {
305
+ MENU_ITEMS.with(|cell| {
306
+ let items = cell.borrow();
307
+ if let Some(i) = items.get(&self.menu_id) {
308
+ i.set_text(&text);
309
+ }
310
+ });
311
+ }
312
+
313
+ fn is_enabled(&self) -> bool {
314
+ MENU_ITEMS.with(|cell| {
315
+ let items = cell.borrow();
316
+ items.get(&self.menu_id).map(|i| i.is_enabled()).unwrap_or(false)
317
+ })
318
+ }
319
+
320
+ fn set_enabled(&self, enabled: bool) {
321
+ MENU_ITEMS.with(|cell| {
322
+ let items = cell.borrow();
323
+ if let Some(i) = items.get(&self.menu_id) {
324
+ i.set_enabled(enabled);
325
+ }
326
+ });
327
+ }
328
+
329
+ fn id(&self) -> String {
330
+ self.menu_id.clone()
331
+ }
332
+
333
+ fn inspect(&self) -> String {
334
+ let text = self.text();
335
+ format!("#<Ranma::MenuItem id={} text={:?}>", self.menu_id, text)
336
+ }
337
+ }
338
+
339
+ // --- CheckMenuItem ---
340
+
341
+ #[magnus::wrap(class = "Ranma::CheckMenuItem", free_immediately, size)]
342
+ pub struct RbCheckMenuItem {
343
+ menu_id: String,
344
+ }
345
+
346
+ impl RbCheckMenuItem {
347
+ fn new(text: String, enabled: bool, checked: bool) -> Self {
348
+ let item = muda::CheckMenuItem::new(&text, enabled, checked, None);
349
+ let id = item.id().0.clone();
350
+ CHECK_MENU_ITEMS.with(|cell| {
351
+ cell.borrow_mut().insert(id.clone(), item);
352
+ });
353
+ RbCheckMenuItem { menu_id: id }
354
+ }
355
+
356
+ fn text(&self) -> String {
357
+ CHECK_MENU_ITEMS.with(|cell| {
358
+ let items = cell.borrow();
359
+ items.get(&self.menu_id).map(|i| i.text()).unwrap_or_default()
360
+ })
361
+ }
362
+
363
+ fn set_text(&self, text: String) {
364
+ CHECK_MENU_ITEMS.with(|cell| {
365
+ let items = cell.borrow();
366
+ if let Some(i) = items.get(&self.menu_id) {
367
+ i.set_text(&text);
368
+ }
369
+ });
370
+ }
371
+
372
+ fn is_enabled(&self) -> bool {
373
+ CHECK_MENU_ITEMS.with(|cell| {
374
+ let items = cell.borrow();
375
+ items.get(&self.menu_id).map(|i| i.is_enabled()).unwrap_or(false)
376
+ })
377
+ }
378
+
379
+ fn set_enabled(&self, enabled: bool) {
380
+ CHECK_MENU_ITEMS.with(|cell| {
381
+ let items = cell.borrow();
382
+ if let Some(i) = items.get(&self.menu_id) {
383
+ i.set_enabled(enabled);
384
+ }
385
+ });
386
+ }
387
+
388
+ fn is_checked(&self) -> bool {
389
+ CHECK_MENU_ITEMS.with(|cell| {
390
+ let items = cell.borrow();
391
+ items.get(&self.menu_id).map(|i| i.is_checked()).unwrap_or(false)
392
+ })
393
+ }
394
+
395
+ fn set_checked(&self, checked: bool) {
396
+ CHECK_MENU_ITEMS.with(|cell| {
397
+ let items = cell.borrow();
398
+ if let Some(i) = items.get(&self.menu_id) {
399
+ i.set_checked(checked);
400
+ }
401
+ });
402
+ }
403
+
404
+ fn id(&self) -> String {
405
+ self.menu_id.clone()
406
+ }
407
+
408
+ fn inspect(&self) -> String {
409
+ let text = self.text();
410
+ let checked = self.is_checked();
411
+ format!("#<Ranma::CheckMenuItem id={} text={:?} checked={}>", self.menu_id, text, checked)
412
+ }
413
+ }
414
+
415
+ // --- PredefinedMenuItem ---
416
+
417
+ #[magnus::wrap(class = "Ranma::PredefinedMenuItem", free_immediately, size)]
418
+ pub struct RbPredefinedMenuItem {
419
+ menu_id: String,
420
+ }
421
+
422
+ impl RbPredefinedMenuItem {
423
+ fn register(item: muda::PredefinedMenuItem) -> Self {
424
+ let id = item.id().0.clone();
425
+ PREDEFINED_ITEMS.with(|cell| {
426
+ cell.borrow_mut().insert(id.clone(), item);
427
+ });
428
+ RbPredefinedMenuItem { menu_id: id }
429
+ }
430
+
431
+ fn separator() -> Self {
432
+ Self::register(muda::PredefinedMenuItem::separator())
433
+ }
434
+
435
+ fn copy(text: Option<String>) -> Self {
436
+ Self::register(muda::PredefinedMenuItem::copy(text.as_deref()))
437
+ }
438
+
439
+ fn cut(text: Option<String>) -> Self {
440
+ Self::register(muda::PredefinedMenuItem::cut(text.as_deref()))
441
+ }
442
+
443
+ fn paste(text: Option<String>) -> Self {
444
+ Self::register(muda::PredefinedMenuItem::paste(text.as_deref()))
445
+ }
446
+
447
+ fn select_all(text: Option<String>) -> Self {
448
+ Self::register(muda::PredefinedMenuItem::select_all(text.as_deref()))
449
+ }
450
+
451
+ fn undo(text: Option<String>) -> Self {
452
+ Self::register(muda::PredefinedMenuItem::undo(text.as_deref()))
453
+ }
454
+
455
+ fn redo(text: Option<String>) -> Self {
456
+ Self::register(muda::PredefinedMenuItem::redo(text.as_deref()))
457
+ }
458
+
459
+ fn minimize(text: Option<String>) -> Self {
460
+ Self::register(muda::PredefinedMenuItem::minimize(text.as_deref()))
461
+ }
462
+
463
+ fn maximize(text: Option<String>) -> Self {
464
+ Self::register(muda::PredefinedMenuItem::maximize(text.as_deref()))
465
+ }
466
+
467
+ fn fullscreen(text: Option<String>) -> Self {
468
+ Self::register(muda::PredefinedMenuItem::fullscreen(text.as_deref()))
469
+ }
470
+
471
+ fn hide(text: Option<String>) -> Self {
472
+ Self::register(muda::PredefinedMenuItem::hide(text.as_deref()))
473
+ }
474
+
475
+ fn hide_others(text: Option<String>) -> Self {
476
+ Self::register(muda::PredefinedMenuItem::hide_others(text.as_deref()))
477
+ }
478
+
479
+ fn show_all(text: Option<String>) -> Self {
480
+ Self::register(muda::PredefinedMenuItem::show_all(text.as_deref()))
481
+ }
482
+
483
+ fn close_window(text: Option<String>) -> Self {
484
+ Self::register(muda::PredefinedMenuItem::close_window(text.as_deref()))
485
+ }
486
+
487
+ fn quit(text: Option<String>) -> Self {
488
+ Self::register(muda::PredefinedMenuItem::quit(text.as_deref()))
489
+ }
490
+
491
+ fn about(text: Option<String>) -> Self {
492
+ let metadata = text.as_ref().map(|t| muda::AboutMetadata {
493
+ name: Some(t.clone()),
494
+ ..Default::default()
495
+ });
496
+ Self::register(muda::PredefinedMenuItem::about(text.as_deref(), metadata))
497
+ }
498
+
499
+ fn services(text: Option<String>) -> Self {
500
+ Self::register(muda::PredefinedMenuItem::services(text.as_deref()))
501
+ }
502
+
503
+ fn bring_all_to_front(text: Option<String>) -> Self {
504
+ Self::register(muda::PredefinedMenuItem::bring_all_to_front(text.as_deref()))
505
+ }
506
+
507
+ fn id(&self) -> String {
508
+ self.menu_id.clone()
509
+ }
510
+
511
+ fn inspect(&self) -> String {
512
+ format!("#<Ranma::PredefinedMenuItem id={}>", self.menu_id)
513
+ }
514
+ }
515
+
516
+ pub fn define_menu_classes(ruby: &Ruby, module: &magnus::RModule) -> Result<(), Error> {
517
+ // Menu
518
+ let menu_class = module.define_class("Menu", ruby.class_object())?;
519
+ menu_class.define_singleton_method("new", function!(RbMenu::new, 0))?;
520
+ menu_class.define_method("append", method!(RbMenu::append, 1))?;
521
+ menu_class.define_method("init_for_nsapp", method!(RbMenu::init_for_nsapp, 0))?;
522
+ menu_class.define_method("id", method!(RbMenu::id, 0))?;
523
+ menu_class.define_method("inspect", method!(RbMenu::inspect, 0))?;
524
+ menu_class.define_method("to_s", method!(RbMenu::inspect, 0))?;
525
+
526
+ // Submenu
527
+ let submenu_class = module.define_class("Submenu", ruby.class_object())?;
528
+ submenu_class.define_singleton_method("new", function!(RbSubmenu::new, 2))?;
529
+ submenu_class.define_method("append", method!(RbSubmenu::append, 1))?;
530
+ submenu_class.define_method("text", method!(RbSubmenu::text, 0))?;
531
+ submenu_class.define_method("text=", method!(RbSubmenu::set_text, 1))?;
532
+ submenu_class.define_method("enabled?", method!(RbSubmenu::is_enabled, 0))?;
533
+ submenu_class.define_method("enabled=", method!(RbSubmenu::set_enabled, 1))?;
534
+ submenu_class.define_method("set_as_windows_menu_for_nsapp", method!(RbSubmenu::set_as_windows_menu_for_nsapp, 0))?;
535
+ submenu_class.define_method("id", method!(RbSubmenu::id, 0))?;
536
+ submenu_class.define_method("inspect", method!(RbSubmenu::inspect, 0))?;
537
+ submenu_class.define_method("to_s", method!(RbSubmenu::inspect, 0))?;
538
+
539
+ // MenuItem
540
+ let menu_item_class = module.define_class("MenuItem", ruby.class_object())?;
541
+ menu_item_class.define_singleton_method("new", function!(RbMenuItem::new, 2))?;
542
+ menu_item_class.define_method("text", method!(RbMenuItem::text, 0))?;
543
+ menu_item_class.define_method("text=", method!(RbMenuItem::set_text, 1))?;
544
+ menu_item_class.define_method("enabled?", method!(RbMenuItem::is_enabled, 0))?;
545
+ menu_item_class.define_method("enabled=", method!(RbMenuItem::set_enabled, 1))?;
546
+ menu_item_class.define_method("id", method!(RbMenuItem::id, 0))?;
547
+ menu_item_class.define_method("inspect", method!(RbMenuItem::inspect, 0))?;
548
+ menu_item_class.define_method("to_s", method!(RbMenuItem::inspect, 0))?;
549
+
550
+ // CheckMenuItem
551
+ let check_item_class = module.define_class("CheckMenuItem", ruby.class_object())?;
552
+ check_item_class.define_singleton_method("new", function!(RbCheckMenuItem::new, 3))?;
553
+ check_item_class.define_method("text", method!(RbCheckMenuItem::text, 0))?;
554
+ check_item_class.define_method("text=", method!(RbCheckMenuItem::set_text, 1))?;
555
+ check_item_class.define_method("enabled?", method!(RbCheckMenuItem::is_enabled, 0))?;
556
+ check_item_class.define_method("enabled=", method!(RbCheckMenuItem::set_enabled, 1))?;
557
+ check_item_class.define_method("checked?", method!(RbCheckMenuItem::is_checked, 0))?;
558
+ check_item_class.define_method("checked=", method!(RbCheckMenuItem::set_checked, 1))?;
559
+ check_item_class.define_method("id", method!(RbCheckMenuItem::id, 0))?;
560
+ check_item_class.define_method("inspect", method!(RbCheckMenuItem::inspect, 0))?;
561
+ check_item_class.define_method("to_s", method!(RbCheckMenuItem::inspect, 0))?;
562
+
563
+ // PredefinedMenuItem
564
+ let predefined_class = module.define_class("PredefinedMenuItem", ruby.class_object())?;
565
+ predefined_class.define_singleton_method("separator", function!(RbPredefinedMenuItem::separator, 0))?;
566
+ predefined_class.define_singleton_method("copy", function!(RbPredefinedMenuItem::copy, 1))?;
567
+ predefined_class.define_singleton_method("cut", function!(RbPredefinedMenuItem::cut, 1))?;
568
+ predefined_class.define_singleton_method("paste", function!(RbPredefinedMenuItem::paste, 1))?;
569
+ predefined_class.define_singleton_method("select_all", function!(RbPredefinedMenuItem::select_all, 1))?;
570
+ predefined_class.define_singleton_method("undo", function!(RbPredefinedMenuItem::undo, 1))?;
571
+ predefined_class.define_singleton_method("redo", function!(RbPredefinedMenuItem::redo, 1))?;
572
+ predefined_class.define_singleton_method("minimize", function!(RbPredefinedMenuItem::minimize, 1))?;
573
+ predefined_class.define_singleton_method("maximize", function!(RbPredefinedMenuItem::maximize, 1))?;
574
+ predefined_class.define_singleton_method("fullscreen", function!(RbPredefinedMenuItem::fullscreen, 1))?;
575
+ predefined_class.define_singleton_method("hide", function!(RbPredefinedMenuItem::hide, 1))?;
576
+ predefined_class.define_singleton_method("hide_others", function!(RbPredefinedMenuItem::hide_others, 1))?;
577
+ predefined_class.define_singleton_method("show_all", function!(RbPredefinedMenuItem::show_all, 1))?;
578
+ predefined_class.define_singleton_method("close_window", function!(RbPredefinedMenuItem::close_window, 1))?;
579
+ predefined_class.define_singleton_method("quit", function!(RbPredefinedMenuItem::quit, 1))?;
580
+ predefined_class.define_singleton_method("about", function!(RbPredefinedMenuItem::about, 1))?;
581
+ predefined_class.define_singleton_method("services", function!(RbPredefinedMenuItem::services, 1))?;
582
+ predefined_class.define_singleton_method("bring_all_to_front", function!(RbPredefinedMenuItem::bring_all_to_front, 1))?;
583
+ predefined_class.define_method("id", method!(RbPredefinedMenuItem::id, 0))?;
584
+ predefined_class.define_method("inspect", method!(RbPredefinedMenuItem::inspect, 0))?;
585
+ predefined_class.define_method("to_s", method!(RbPredefinedMenuItem::inspect, 0))?;
586
+
587
+ Ok(())
588
+ }