1#[doc(hidden)]
2#[macro_export]
3macro_rules! impl_widget_ext {
5 ($name: ident, $flname: ident) => {
6 #[cfg(not(feature = "single-threaded"))]
7 unsafe impl Send for $name {}
8 #[cfg(not(feature = "single-threaded"))]
9 unsafe impl Sync for $name {}
10
11 impl PartialEq for $name {
12 fn eq(&self, other: &Self) -> bool {
13 self.inner.widget() == other.inner.widget()
14 }
15 }
16 impl Eq for $name {}
17 impl Clone for $name {
18 fn clone(&self) -> $name {
19
20 $name {
21 inner: self.inner.clone(),
22 is_derived: self.is_derived,
23 }
24 }
25 }
26
27 paste::paste! {
28 $crate::macros::utils::widget_props!($name);
29
30 unsafe impl WidgetExt for $name {
31 fn set_label(&mut self, title: &str) {
32 if self.as_window().is_some() {
33 assert!($crate::app::is_ui_thread());
34 }
35 unsafe {
36 let temp = CString::safe_new(title);
37 [<$flname _set_label>](self.inner.widget() as _, temp.as_ptr());
38 }
39 }
40
41 fn unset_label(&mut self) {
42 if self.as_window().is_some() {
43 assert!($crate::app::is_ui_thread());
44 }
45 unsafe {
46 [<$flname _set_label>](self.inner.widget() as _, std::ptr::null() as _);
47 }
48 }
49
50 fn redraw(&mut self) {
51 unsafe {
52 [<$flname _redraw>](self.inner.widget() as _);
53 }
54 }
55
56 fn show(&mut self) {
57 if self.as_window().is_some() {
58 assert!($crate::app::is_ui_thread());
59 }
60 unsafe { [<$flname _show>](self.inner.widget() as _) }
61 }
62
63 fn hide(&mut self) {
64 if self.as_window().is_some() {
65 assert!($crate::app::is_ui_thread());
66 }
67 unsafe { [<$flname _hide>](self.inner.widget() as _) }
68 }
69
70 fn x(&self) -> i32 {
71 unsafe { [<$flname _x>](self.inner.widget() as _) }
72 }
73
74 fn y(&self) -> i32 {
75 unsafe { [<$flname _y>](self.inner.widget() as _) }
76 }
77
78 fn w(&self) -> i32 {
79 unsafe { [<$flname _width>](self.inner.widget() as _) }
80 }
81
82 fn h(&self) -> i32 {
83 unsafe { [<$flname _height>](self.inner.widget() as _) }
84 }
85
86 fn label(&self) -> Option<String> {
87 unsafe {
88 let ptr = [<$flname _label>](self.inner.widget() as _) as *mut std::os::raw::c_char;
89 let s = if ptr.is_null() {
90 None
91 } else {
92 Some(CStr::from_ptr(ptr).to_string_lossy().to_string())
93 };
94 s
95 }
96 }
97
98 fn measure_label(&self) -> (i32, i32) {
99 let mut x = 0;
100 let mut y = 0;
101 unsafe {
102 [<$flname _measure_label>](self.inner.widget() as _, &mut x, &mut y);
103 }
104 (x, y)
105 }
106
107 fn as_widget_ptr(&self) -> *mut fltk_sys::widget::Fl_Widget {
108 self.inner.widget() as *mut fltk_sys::widget::Fl_Widget
109 }
110
111 fn activate(&mut self) {
112 unsafe { [<$flname _activate>](self.inner.widget() as _) }
113 }
114
115 fn deactivate(&mut self) {
116 unsafe { [<$flname _deactivate>](self.inner.widget() as _) }
117 }
118
119 fn redraw_label(&mut self) {
120 unsafe { [<$flname _redraw_label>](self.inner.widget() as _) }
121 }
122
123 fn resize(&mut self, x: i32, y: i32, width: i32, height: i32) {
124 unsafe { [<$flname _resize>](self.inner.widget() as _, x, y, width, height) }
125 }
126
127 fn widget_resize(&mut self, x: i32, y: i32, width: i32, height: i32) {
128 assert!(self.is_derived);
129 unsafe { [<$flname _widget_resize>](self.inner.widget() as _, x, y, width, height) }
130 }
131
132 fn tooltip(&self) -> Option<String> {
133 unsafe {
134 let tooltip_ptr = [<$flname _tooltip>](self.inner.widget() as _);
135 let s = if tooltip_ptr.is_null() {
136 None
137 } else {
138 Some(
139 CStr::from_ptr(tooltip_ptr as *mut std::os::raw::c_char)
140 .to_string_lossy()
141 .to_string(),
142 )
143 };
144 s
145 }
146 }
147
148 fn set_tooltip(&mut self, txt: &str) {
149 let txt = CString::safe_new(txt);
150 unsafe {
151 [<$flname _set_tooltip>](
152 self.inner.widget() as _,
153 txt.as_ptr() as *mut std::os::raw::c_char,
154 )
155 }
156 }
157
158 fn color(&self) -> $crate::enums::Color {
159 unsafe { std::mem::transmute([<$flname _color>](self.inner.widget() as _)) }
160 }
161
162 fn set_color(&mut self, color: $crate::enums::Color) {
163 unsafe { [<$flname _set_color>](self.inner.widget() as _, color.bits() as u32) }
164 }
165
166 fn label_color(&self) -> $crate::enums::Color {
167 unsafe { std::mem::transmute([<$flname _label_color>](self.inner.widget() as _)) }
168 }
169
170 fn set_label_color(&mut self, color: $crate::enums::Color) {
171 unsafe {
172 [<$flname _set_label_color>](self.inner.widget() as _, color.bits() as u32)
173 }
174 }
175
176 fn label_font(&self) -> $crate::enums::Font {
177 unsafe { std::mem::transmute([<$flname _label_font>](self.inner.widget() as _)) }
178 }
179
180 fn set_label_font(&mut self, font: $crate::enums::Font) {
181 unsafe { [<$flname _set_label_font>](self.inner.widget() as _, font.bits() as i32) }
182 }
183
184 fn label_size(&self) -> i32 {
185 unsafe { [<$flname _label_size>](self.inner.widget() as _) }
186 }
187
188 fn set_label_size(&mut self, sz: i32) {
189 let sz = if sz < 1 { 1 } else { sz };
190 unsafe { [<$flname _set_label_size>](self.inner.widget() as _, sz) }
191 }
192
193 fn label_type(&self) -> $crate::enums::LabelType {
194 unsafe { std::mem::transmute([<$flname _label_type>](self.inner.widget() as _)) }
195 }
196
197 fn set_label_type(&mut self, typ: $crate::enums::LabelType) {
198 unsafe {
199 [<$flname _set_label_type>](self.inner.widget() as _, typ as i32);
200 }
201 }
202
203 fn frame(&self) -> $crate::enums::FrameType {
204 unsafe { $crate::enums::FrameType::from_i32([<$flname _box>](self.inner.widget() as _)) }
205 }
206
207 fn set_frame(&mut self, typ: $crate::enums::FrameType) {
208 unsafe {
209 [<$flname _set_box>](self.inner.widget() as _, typ.as_i32());
210 }
211 }
212
213 fn changed(&self) -> bool {
214 unsafe { [<$flname _changed>](self.inner.widget() as _) != 0 }
215 }
216
217 fn set_changed(&mut self) {
218 unsafe { [<$flname _set_changed>](self.inner.widget() as _) }
219 }
220
221 fn clear_changed(&mut self) {
222 unsafe { [<$flname _clear_changed>](self.inner.widget() as _) }
223 }
224
225 fn align(&self) -> $crate::enums::Align {
226 unsafe { std::mem::transmute([<$flname _align>](self.inner.widget() as _)) }
227 }
228
229 fn set_align(&mut self, align: $crate::enums::Align) {
230 unsafe { [<$flname _set_align>](self.inner.widget() as _, align.bits() as i32) }
231 }
232
233 fn set_when(&mut self, trigger: $crate::enums::When) {
234 unsafe { [<$flname _set_when>](self.inner.widget() as _, trigger.bits() as i32) }
235 }
236
237 fn when(&self) -> $crate::enums::When {
238 unsafe { std::mem::transmute([<$flname _when>](self.inner.widget() as _)) }
239 }
240
241 fn parent(&self) -> Option<$crate::group::Group> {
242 unsafe {
243 let x = [<$flname _parent>](self.inner.widget() as _);
244 if x.is_null() {
245 None
246 } else {
247 Some($crate::group::Group::from_widget_ptr(x as *mut _))
248 }
249 }
250 }
251
252 fn selection_color(&self) -> $crate::enums::Color {
253 unsafe { std::mem::transmute([<$flname _selection_color>](self.inner.widget() as _)) }
254 }
255
256 fn set_selection_color(&mut self, color: $crate::enums::Color) {
257 unsafe {
258 [<$flname _set_selection_color>](self.inner.widget() as _, color.bits() as u32);
259 }
260 }
261
262 fn do_callback(&mut self) {
263 unsafe {
264 [<$flname _do_callback>](self.inner.widget() as _);
265 }
266 }
267
268 fn window(&self) -> Option<Box<dyn WindowExt>> {
269 unsafe {
270 let wind_ptr = [<$flname _window>](self.inner.widget() as _);
271 if wind_ptr.is_null() {
272 None
273 } else {
274 Some(Box::new($crate::window::Window::from_widget_ptr(
275 wind_ptr as *mut fltk_sys::widget::Fl_Widget,
276 )))
277 }
278 }
279 }
280
281 fn top_window(&self) -> Option<Box<dyn WindowExt>> {
282 unsafe {
283 let wind_ptr = [<$flname _top_window>](self.inner.widget() as _);
284 if wind_ptr.is_null() {
285 None
286 } else {
287 Some(Box::new($crate::window::Window::from_widget_ptr(
288 wind_ptr as *mut fltk_sys::widget::Fl_Widget,
289 )))
290 }
291 }
292 }
293
294 fn takes_events(&self) -> bool {
295 unsafe { [<$flname _takes_events>](self.inner.widget() as _) != 0 }
296 }
297
298 unsafe fn user_data(&self) -> Option<Box<dyn FnMut()>> { unsafe {
299 let ptr = [<$flname _user_data>](self.inner.widget() as _);
300 if ptr.is_null() {
301 None
302 } else {
303 let x = ptr as *mut Box<dyn FnMut()>;
304 let x = Box::from_raw(x);
305 [<$flname _set_callback>](self.inner.widget() as _, None, std::ptr::null_mut());
306 Some(*x)
307 }
308 }}
309
310 unsafe fn raw_user_data(&self) -> *mut std::os::raw::c_void { unsafe {
311 [<$flname _user_data>](self.inner.widget() as _)
312 }}
313
314 unsafe fn set_raw_user_data(&mut self, data: *mut std::os::raw::c_void) { unsafe {
315 [<$flname _set_user_data>](self.inner.widget() as _, data)
316 }}
317
318 fn take_focus(&mut self) -> Result<(), FltkError> {
319 unsafe {
320 match [<$flname _take_focus>](self.inner.widget() as _) {
321 0 => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
322 _ => Ok(()),
323 }
324 }
325 }
326
327 fn set_visible_focus(&mut self) {
328 unsafe { [<$flname _set_visible_focus>](self.inner.widget() as _) }
329 }
330
331 fn clear_visible_focus(&mut self) {
332 unsafe { [<$flname _clear_visible_focus>](self.inner.widget() as _) }
333 }
334
335 fn visible_focus(&mut self, v: bool) {
336 unsafe { [<$flname _visible_focus>](self.inner.widget() as _, v as i32) }
337 }
338
339 fn has_visible_focus(&self) -> bool {
340 unsafe { [<$flname _has_visible_focus>](self.inner.widget() as _) != 0 }
341 }
342
343 fn has_focus(&self) -> bool {
344 unsafe { fltk_sys::fl::Fl_focus() == self.inner.widget() as _ }
345 }
346
347 fn was_deleted(&self) -> bool {
348 self.inner.deleted()
349 }
350
351 fn damage(&self) -> bool {
352 unsafe { [<$flname _damage>](self.inner.widget() as _) != 0 }
353 }
354
355 fn set_damage(&mut self, flag: bool) {
356 let flag = if flag { 0x80 } else { 0 };
357 unsafe { [<$flname _set_damage>](self.inner.widget() as _, flag) }
358 }
359
360 fn damage_type(&self) -> $crate::enums::Damage {
361 unsafe { std::mem::transmute([<$flname _damage>](self.inner.widget() as _)) }
362 }
363
364 fn set_damage_type(&mut self, mask: $crate::enums::Damage) {
365 unsafe { [<$flname _set_damage>](self.inner.widget() as _, mask.bits()) }
366 }
367
368 fn set_damage_area(&mut self, mask: $crate::enums::Damage, x: i32, y: i32, w: i32, h: i32) {
369 unsafe { [<$flname _set_damage_area>](self.inner.widget() as _, mask.bits(), x, y, w, h) }
370 }
371
372 fn clear_damage(&mut self) {
373 unsafe { [<$flname _clear_damage>](self.inner.widget() as _) }
374 }
375
376 fn as_window(&self) -> Option<Box<dyn WindowExt>> {
377 unsafe {
378 let ptr = [<$flname _as_window>](self.inner.widget() as _);
379 if ptr.is_null() {
380 return None;
381 }
382 Some(Box::new($crate::window::Window::from_widget_ptr(
383 ptr as *mut fltk_sys::widget::Fl_Widget,
384 )))
385 }
386 }
387
388 fn as_group(&self) -> Option<$crate::group::Group> {
389 unsafe {
390 let ptr = [<$flname _as_group>](self.inner.widget() as _);
391 if ptr.is_null() {
392 return None;
393 }
394 Some($crate::group::Group::from_widget_ptr(
395 ptr as *mut fltk_sys::widget::Fl_Widget,
396 ))
397 }
398 }
399
400 fn inside<W: WidgetExt>(&self, wid: &W) -> bool {
401 unsafe {
402 [<$flname _inside>](
403 self.inner.widget() as _,
404 wid.as_widget_ptr() as *mut std::os::raw::c_void,
405 ) != 0
406 }
407 }
408
409 fn get_type<T: WidgetType>(&self) -> T {
410 unsafe { T::from_i32([<$flname _get_type>](self.inner.widget() as _)) }
411 }
412
413 fn set_type<T: WidgetType>(&mut self, typ: T) {
414 unsafe {
415 [<$flname _set_type>](self.inner.widget() as _, typ.to_i32());
416 }
417 }
418
419 fn set_image<I: ImageExt>(&mut self, image: Option<I>) {
420 if let Some(image) = image {
421 assert!(!image.was_deleted());
422 unsafe {
423 [<$flname _set_image>](
424 self.inner.widget() as _,
425 image.as_image_ptr() as *mut _,
426 )
427 }
428 } else {
429 unsafe {
430 [<$flname _set_image>](
431 self.inner.widget() as _,
432 std::ptr::null_mut() as *mut std::os::raw::c_void,
433 )
434 }
435 }
436 }
437
438 fn set_image_scaled<I: ImageExt>(&mut self, image: Option<I>) {
439 if let Some(mut image) = image {
440 assert!(!image.was_deleted());
441 image.scale(self.w(), self.h(), false, true);
442 unsafe {
443 [<$flname _set_image>](
444 self.inner.widget() as _,
445 image.as_image_ptr() as *mut _,
446 )
447 }
448 } else {
449 unsafe {
450 [<$flname _set_image>](
451 self.inner.widget() as _,
452 std::ptr::null_mut() as *mut std::os::raw::c_void,
453 )
454 }
455 }
456 }
457
458 fn image(&self) -> Option<Box<dyn ImageExt>> {
459 unsafe {
460 let image_ptr = [<$flname _image>](self.inner.widget() as _);
461 if image_ptr.is_null() {
462 None
463 } else {
464 let img =
465 $crate::image::Image::from_image_ptr(image_ptr as *mut fltk_sys::image::Fl_Image);
466 Some(Box::new(img))
467 }
468 }
469 }
470
471 fn set_deimage<I: ImageExt>(&mut self, image: Option<I>) {
472 if let Some(image) = image {
473 assert!(!image.was_deleted());
474 unsafe {
475 [<$flname _set_deimage>](
476 self.inner.widget() as _,
477 image.as_image_ptr() as *mut _,
478 )
479 }
480 } else {
481 unsafe {
482 [<$flname _set_deimage>](
483 self.inner.widget() as _,
484 std::ptr::null_mut() as *mut std::os::raw::c_void,
485 )
486 }
487 }
488 }
489
490 fn set_deimage_scaled<I: ImageExt>(&mut self, image: Option<I>) {
491 if let Some(mut image) = image {
492 assert!(!image.was_deleted());
493 image.scale(self.w(), self.h(), false, true);
494 unsafe {
495 [<$flname _set_deimage>](
496 self.inner.widget() as _,
497 image.as_image_ptr() as *mut _,
498 )
499 }
500 } else {
501 unsafe {
502 [<$flname _set_deimage>](
503 self.inner.widget() as _,
504 std::ptr::null_mut() as *mut std::os::raw::c_void,
505 )
506 }
507 }
508 }
509
510 fn deimage(&self) -> Option<Box<dyn ImageExt>> {
511 unsafe {
512 let image_ptr = [<$flname _deimage>](self.inner.widget() as _);
513 if image_ptr.is_null() {
514 None
515 } else {
516 let img =
517 $crate::image::Image::from_image_ptr(image_ptr as *mut fltk_sys::image::Fl_Image);
518 Some(Box::new(img))
519 }
520 }
521 }
522
523 fn set_callback<F: FnMut(&mut Self) + 'static>(&mut self, cb: F) {
524 unsafe {
525 unsafe extern "C" fn shim_derived(wid: *mut Fl_Widget, data: *mut std::os::raw::c_void) { unsafe {
526 let mut wid = $name::from_widget_ptr(wid as *mut _);
527 wid.assume_derived();
528 let a = data as *mut Box<dyn FnMut(&mut $name)>;
529 let f: &mut (dyn FnMut(&mut $name)) = &mut **a;
530 let _ =
531 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&mut wid)));
532 }}
533 unsafe extern "C" fn shim_not_derived(wid: *mut Fl_Widget, data: *mut std::os::raw::c_void) { unsafe {
534 let mut wid = $name::from_widget_ptr(wid as *mut _);
535 let a = data as *mut Box<dyn FnMut(&mut $name)>;
536 let f: &mut (dyn FnMut(&mut $name)) = &mut **a;
537 let _ =
538 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&mut wid)));
539 }}
540 let mut _old_data = None;
541 if self.is_derived {
542 _old_data = self.user_data();
543 }
544 let a: *mut Box<dyn FnMut(&mut Self)> = Box::into_raw(Box::new(Box::new(cb)));
545 let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void;
546 let callback: Fl_Callback = Some(if self.is_derived { shim_derived } else { shim_not_derived });
547 [<$flname _set_callback>](self.inner.widget() as _, callback, data);
548 }
549 }
550
551 fn emit<T: 'static + Clone + Send + Sync>(
552 &mut self,
553 sender: $crate::app::Sender<T>,
554 msg: T,
555 ) {
556
557 self.set_callback(move |_| sender.send(msg.clone()))
558 }
559
560 unsafe fn as_widget<W: WidgetBase>(&self) -> W { unsafe {
561 W::from_widget_ptr(self.as_widget_ptr() as *mut _)
562 }}
563
564 fn visible(&self) -> bool {
565 unsafe { [<$flname _visible>](self.inner.widget() as _) != 0 }
566 }
567
568 fn visible_r(&self) -> bool {
569 unsafe { [<$flname _visible_r>](self.inner.widget() as _) != 0 }
570 }
571
572 fn is_same<W: WidgetExt>(&self, other: &W) -> bool {
573 self.as_widget_ptr() == other.as_widget_ptr()
574 }
575
576 fn active(&self) -> bool {
577 unsafe { [<$flname _active>](self.inner.widget() as _) != 0 }
578 }
579
580 fn active_r(&self) -> bool {
581 unsafe { [<$flname _active_r>](self.inner.widget() as _) != 0 }
582 }
583
584 fn callback(&self) -> Option<Box<dyn FnMut()>> {
585 unsafe {
586 let cb = [<$flname _callback>](self.inner.widget() as _);
587 let data = [<$flname _user_data>](self.inner.widget() as _);
588 if !data.is_null() {
589 return None;
590 }
591 let s = self.clone();
592 if let Some(cb) = cb {
593 let cb_1 = Box::new(move || {
594 cb(s.as_widget_ptr() as _, std::ptr::null_mut());
595 });
596 Some(cb_1)
597 } else {
598 None
599 }
600 }
601 }
602
603 fn handle_event(&mut self, event: $crate::enums::Event) -> bool {
604 unsafe { [<$flname _handle_event>](self.inner.widget() as _, event.bits()) != 0 }
605 }
606
607 fn is_derived(&self) -> bool {
608 self.is_derived
609 }
610 }
611 }
612 };
613}
614
615#[doc(hidden)]
616#[macro_export]
617macro_rules! impl_widget_base {
619 ($name: ident, $flname: ident) => {
620 paste::paste! {
621 unsafe impl WidgetBase for $name {
622 fn delete(wid: Self) {
623 if let Some(mut parent) = wid.parent() {
624 parent.remove(&wid);
625 }
626 unsafe {
627 [<$flname _delete>](wid.as_widget_ptr() as _);
628 }
629 }
630
631 unsafe fn from_widget_ptr(ptr: *mut fltk_sys::widget::Fl_Widget) -> Self {
632 assert!(!ptr.is_null());
633 let tracker =
634 $crate::widget::WidgetTracker::new(ptr as _);
635 let temp = $name {
636 inner: tracker,
637 is_derived: false,
638 };
639 temp
640 }
641
642 unsafe fn from_widget<W: WidgetExt>(w: W) -> Self { unsafe {
643 Self::from_widget_ptr(w.as_widget_ptr() as *mut _)
644 }}
645
646 fn handle<F: FnMut(&mut Self, $crate::enums::Event) -> bool + 'static>(&mut self, cb: F) {
647 assert!(self.is_derived);
648 unsafe {
652 unsafe extern "C" fn shim(
653 wid: *mut Fl_Widget,
654 ev: std::os::raw::c_int,
655 data: *mut std::os::raw::c_void,
656 ) -> i32 { unsafe {
657 let mut wid = $name::from_widget_ptr(wid as *mut _);
658 wid.assume_derived();
659 let ev: $crate::enums::Event = std::mem::transmute(ev);
660 let a: *mut Box<dyn FnMut(&mut $name, $crate::enums::Event) -> bool> =
661 data as *mut Box<dyn FnMut(&mut $name, $crate::enums::Event) -> bool>;
662 let f: &mut (dyn FnMut(&mut $name, $crate::enums::Event) -> bool) = &mut **a;
663 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
664 match f(&mut wid, ev) {
665 true => return 1,
666 false => return 0,
667 }
668 }));
669 if let Ok(ret) = result {
670 ret
671 } else {
672 0
673 }
674 }}
675 let mut _old_data = None;
676 if self.is_derived {
677 _old_data = self.handle_data();
678 }
679 let a: *mut Box<dyn FnMut(&mut Self, $crate::enums::Event) -> bool> =
680 Box::into_raw(Box::new(Box::new(cb)));
681 let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void;
682 let callback: custom_handler_callback = Some(shim);
683 [<$flname _handle>](self.inner.widget() as _, callback, data);
684 }
685 }
686
687 fn draw<F: FnMut(&mut Self) + 'static>(&mut self, cb: F) {
688 assert!(self.is_derived);
689 unsafe {
690 unsafe extern "C" fn shim(wid: *mut Fl_Widget, data: *mut std::os::raw::c_void) { unsafe {
691 let mut wid = $name::from_widget_ptr(wid as *mut _);
692 wid.assume_derived();
693 let a: *mut Box<dyn FnMut(&mut $name)> =
694 data as *mut Box<dyn FnMut(&mut $name)>;
695 let f: &mut (dyn FnMut(&mut $name)) = &mut **a;
696 let _ =
697 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&mut wid)));
698 }}
699 let mut _old_data = None;
700 if self.is_derived {
701 _old_data = self.draw_data();
702 }
703 let a: *mut Box<dyn FnMut(&mut Self)> = Box::into_raw(Box::new(Box::new(cb)));
704 let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void;
705 let callback: custom_draw_callback = Some(shim);
706 [<$flname _draw>](self.inner.widget() as _, callback, data);
707 }
708 }
709
710 unsafe fn draw_data(&self) -> Option<Box<dyn FnMut()>> { unsafe {
711 let ptr = [<$flname _draw_data>](self.inner.widget() as _);
712 if ptr.is_null() {
713 return None;
714 }
715 let data = ptr as *mut Box<dyn FnMut()>;
716 let data = Box::from_raw(data);
717 [<$flname _draw>](self.inner.widget() as _, None, std::ptr::null_mut());
718 Some(*data)
719 }}
720
721 unsafe fn handle_data(&self) -> Option<Box<dyn FnMut($crate::enums::Event) -> bool>> { unsafe {
722 let ptr = [<$flname _handle_data>](self.inner.widget() as _);
723 if ptr.is_null() {
724 return None;
725 }
726 let data = ptr as *mut Box<dyn FnMut($crate::enums::Event) -> bool>;
727 let data = Box::from_raw(data);
728 [<$flname _handle>](self.inner.widget() as _, None, std::ptr::null_mut());
729 Some(*data)
730 }}
731
732 fn resize_callback<F: FnMut(&mut Self, i32, i32, i32, i32) + 'static>(
733 &mut self,
734 cb: F,
735 ) {
736 assert!(self.is_derived);
737 unsafe {
738 unsafe extern "C" fn shim(
739 wid: *mut Fl_Widget,
740 x: i32,
741 y: i32,
742 w: i32,
743 h: i32,
744 data: *mut std::os::raw::c_void,
745 ) { unsafe {
746 let mut wid = $name::from_widget_ptr(wid as *mut _);
747 wid.assume_derived();
748 let a: *mut Box<dyn FnMut(&mut $name, i32, i32, i32, i32)> =
749 data as *mut Box<dyn FnMut(&mut $name, i32, i32, i32, i32)>;
750 let f: &mut (dyn FnMut(&mut $name, i32, i32, i32, i32)) = &mut **a;
751 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
752 f(&mut wid, x, y, w, h)
753 }));
754 }}
755 let a: *mut Box<dyn FnMut(&mut Self, i32, i32, i32, i32)> =
756 Box::into_raw(Box::new(Box::new(cb)));
757 let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void;
758 let callback: Option<
759 unsafe extern "C" fn(*mut Fl_Widget, i32, i32, i32, i32, *mut std::os::raw::c_void),
760 > = Some(shim);
761 [<$flname _resize_callback>](self.inner.widget() as _, callback, data);
762 }
763 }
764
765 unsafe fn assume_derived(&mut self) {
766 self.is_derived = true
767 }
768
769 fn from_dyn_widget<W: WidgetExt>(w: &W) -> Option<Self> {
770 Self::from_dyn_widget_ptr(w.as_widget_ptr() as _)
771 }
772
773 fn from_dyn_widget_ptr(w: *mut fltk_sys::widget::Fl_Widget) -> Option<Self> {
774 let ptr = unsafe { [<$flname _from_dyn_ptr>](w as _) };
775 if ptr.is_null() {
776 None
777 } else {
778 unsafe {
779 let tracker = $crate::widget::WidgetTracker::new(ptr as _);
780 let temp = Some(Self {
781 inner: tracker,
782 is_derived: .is_null(),
783 });
784 temp
785 }
786 }
787 }
788
789 fn super_draw(&mut self, flag: bool) {
790 assert!(self.is_derived);
791 unsafe {
792 [<$flname _super_draw>](self.inner.widget() as _, i32::from(flag))
793 }
794 }
795
796 fn super_draw_first(&mut self, flag: bool) {
797 assert!(self.is_derived);
798 unsafe {
799 [<$flname _super_draw_first>](self.inner.widget() as _, i32::from(flag))
800 }
801 }
802
803 fn super_handle_first(&mut self, flag: bool) {
804 assert!(self.is_derived);
805 unsafe {
806 [<$flname _super_handle_first>](self.inner.widget() as _, i32::from(flag))
807 }
808 }
809 }
810 }
811 };
812}
813
814#[doc(hidden)]
815#[macro_export]
816macro_rules! impl_widget_default {
817 ($name: ident, $flname: ident) => {
818 impl Default for $name {
819 fn default() -> Self {
820 Self::new(0, 0, 0, 0, None)
821 }
822 }
823 paste::paste!{
824 impl $name {
825 pub fn new<'a, T: Into<Option<&'a str>>>(
837 x: i32,
838 y: i32,
839 width: i32,
840 height: i32,
841 title: T,
842 ) -> $name {
843 let temp = if let Some(title) = title.into() {
844 CString::safe_new(title).into_raw()
845 } else {
846 std::ptr::null_mut()
847 };
848 unsafe {
849 let widget_ptr = [<$flname _new>](x, y, width, height, temp);
850 assert!(!widget_ptr.is_null());
851 let tracker = $crate::widget::WidgetTracker::new(
852 widget_ptr as _
853 );
854 unsafe extern "C" fn shim(wid: *mut Fl_Widget, _data: *mut std::os::raw::c_void) { unsafe {
855 let user_data = [<$flname _user_data>](wid as _);
856 let draw_data = [<$flname _draw_data>](wid as _);
857 let handle_data = [<$flname _handle_data>](wid as _);
858 $crate::app::add_timeout(0., move |h| {
859 if !user_data.is_null() {
860 let _x = Box::from_raw(user_data as *mut Box<dyn FnMut()>);
861 }
862 if !draw_data.is_null() {
863 let _x = Box::from_raw(draw_data as *mut Box<dyn FnMut()>);
864 }
865 if !handle_data.is_null() {
866 let _x = Box::from_raw(handle_data as *mut Box<dyn FnMut()>);
867 }
868 $crate::app::remove_timeout(h);
869 });
870 }}
871 [<$flname _set_deletion_callback>](widget_ptr, Some(shim), std::ptr::null_mut());
872 $name {
873 inner: tracker,
874 is_derived: true,
875 }
876 }
877 }
878 pub fn default_fill() -> Self {
880 Self::default().size_of_parent().center_of_parent()
881 }
882 }
883 }
884 };
885}
886
887#[doc(hidden)]
888#[macro_export]
889macro_rules! impl_widget_type {
891 ($name: ident) => {
892 impl WidgetType for $name {
893 fn to_i32(self) -> i32 {
894 self as i32
895 }
896
897 fn from_i32(val: i32) -> $name {
898 unsafe { std::mem::transmute(val) }
899 }
900 }
901 };
902}
903
904pub use impl_widget_base;
905pub use impl_widget_default;
906pub use impl_widget_ext;
907pub use impl_widget_type;
908
909#[doc(hidden)]
910#[macro_export]
911macro_rules! impl_widget_ext_via {
913 ($widget:ty, $member:tt) => {
914 impl WidgetProps for $widget {
915 fn with_pos(mut self, x: i32, y: i32) -> Self {
916 self.$member = self.$member.with_pos(x, y);
917 self
918 }
919
920 fn with_size(mut self, width: i32, height: i32) -> Self {
921 self.$member = self.$member.with_size(width, height);
922 self
923 }
924
925 fn with_label(mut self, title: &str) -> Self {
926 self.$member = self.$member.with_label(title);
927 self
928 }
929
930 fn with_align(mut self, align: $crate::enums::Align) -> Self {
931 self.$member = self.$member.with_align(align);
932 self
933 }
934
935 fn with_type<T: WidgetType>(mut self, typ: T) -> Self {
936 self.$member = self.$member.with_type(typ);
937 self
938 }
939
940 fn below_of<W: WidgetExt>(mut self, wid: &W, padding: i32) -> Self {
941 self.$member = self.$member.below_of(wid, padding);
942 self
943 }
944
945 fn above_of<W: WidgetExt>(mut self, wid: &W, padding: i32) -> Self {
946 self.$member = self.$member.above_of(wid, padding);
947 self
948 }
949
950 fn right_of<W: WidgetExt>(mut self, wid: &W, padding: i32) -> Self {
951 self.$member = self.$member.right_of(wid, padding);
952 self
953 }
954
955 fn left_of<W: WidgetExt>(mut self, wid: &W, padding: i32) -> Self {
956 self.$member = self.$member.left_of(wid, padding);
957 self
958 }
959
960 fn center_of<W: WidgetExt>(mut self, w: &W) -> Self {
961 self.$member = self.$member.center_of(w);
962 self
963 }
964
965 fn center_x<W: WidgetExt>(mut self, w: &W) -> Self {
966 self.$member = self.$member.center_x(w);
967 self
968 }
969
970 fn center_y<W: WidgetExt>(mut self, w: &W) -> Self {
971 self.$member = self.$member.center_y(w);
972 self
973 }
974
975 fn center_of_parent(mut self) -> Self {
976 self.$member = self.$member.center_of_parent();
977 self
978 }
979
980 fn size_of<W: WidgetExt>(mut self, w: &W) -> Self {
981 self.$member = self.$member.size_of(w);
982 self
983 }
984
985 fn size_of_parent(mut self) -> Self {
986 self.$member = self.$member.size_of_parent();
987 self
988 }
989 }
990 unsafe impl WidgetExt for $widget {
991 fn set_label<'a, T: Into<Option<&'a str>>>(&mut self, title: T) {
992 self.$member.set_label(title)
993 }
994
995 fn redraw(&mut self) {
996 self.$member.redraw()
997 }
998
999 fn show(&mut self) {
1000 self.$member.show()
1001 }
1002
1003 fn hide(&mut self) {
1004 self.$member.hide()
1005 }
1006
1007 fn x(&self) -> i32 {
1008 self.$member.x()
1009 }
1010
1011 fn y(&self) -> i32 {
1012 self.$member.y()
1013 }
1014
1015 fn w(&self) -> i32 {
1016 self.$member.w()
1017 }
1018
1019 fn h(&self) -> i32 {
1020 self.$member.h()
1021 }
1022
1023 fn label(&self) -> Option<String> {
1024 self.$member.label()
1025 }
1026
1027 fn measure_label(&self) -> (i32, i32) {
1028 self.$member.measure_label()
1029 }
1030
1031 fn as_widget_ptr(&self) -> $crate::app::WidgetPtr {
1032 self.$member.as_widget_ptr()
1033 }
1034
1035 fn inside<W: WidgetExt>(&self, wid: &W) -> bool {
1036 self.$member.inside(wid)
1037 }
1038
1039 fn get_type<T: WidgetType>(&self) -> T {
1040 self.$member.get_type()
1041 }
1042
1043 fn set_type<T: WidgetType>(&mut self, typ: T) {
1044 self.$member.set_type(typ)
1045 }
1046
1047 fn set_image<I: ImageExt>(&mut self, image: Option<I>) {
1048 self.$member.set_image(image)
1049 }
1050
1051 fn set_image_scaled<I: ImageExt>(&mut self, image: Option<I>) {
1052 self.$member.set_image_scaled(image)
1053 }
1054
1055 fn image(&self) -> Option<Box<dyn ImageExt>> {
1056 self.$member.image()
1057 }
1058
1059 fn set_deimage<I: ImageExt>(&mut self, image: Option<I>) {
1060 self.$member.set_deimage(image)
1061 }
1062
1063 fn set_deimage_scaled<I: ImageExt>(&mut self, image: Option<I>) {
1064 self.$member.set_deimage_scaled(image)
1065 }
1066
1067 fn deimage(&self) -> Option<Box<dyn ImageExt>> {
1068 self.$member.deimage()
1069 }
1070
1071 fn set_callback<F: FnMut(&mut Self) + 'static>(&mut self, mut cb: F) {
1072 let mut widget = self.clone();
1073 self.$member.set_callback(move |_| {
1074 cb(&mut widget);
1075 });
1076 }
1077
1078 fn emit<T: 'static + Clone + Send + Sync>(
1079 &mut self,
1080 sender: $crate::app::Sender<T>,
1081 msg: T,
1082 ) {
1083 self.$member.emit(sender, msg)
1084 }
1085
1086 fn activate(&mut self) {
1087 self.$member.activate()
1088 }
1089
1090 fn deactivate(&mut self) {
1091 self.$member.deactivate()
1092 }
1093
1094 fn redraw_label(&mut self) {
1095 self.$member.redraw_label()
1096 }
1097
1098 fn resize(&mut self, x: i32, y: i32, width: i32, height: i32) {
1099 self.$member.resize(x, y, width, height)
1100 }
1101
1102 fn tooltip(&self) -> Option<String> {
1103 self.$member.tooltip()
1104 }
1105
1106 fn set_tooltip(&mut self, txt: &str) {
1107 self.$member.set_tooltip(txt)
1108 }
1109
1110 fn color(&self) -> $crate::enums::Color {
1111 self.$member.color()
1112 }
1113
1114 fn set_color(&mut self, color: $crate::enums::Color) {
1115 self.$member.set_color(color)
1116 }
1117
1118 fn label_color(&self) -> $crate::enums::Color {
1119 self.$member.label_color()
1120 }
1121
1122 fn set_label_color(&mut self, color: $crate::enums::Color) {
1123 self.$member.set_label_color(color)
1124 }
1125
1126 fn label_font(&self) -> $crate::enums::Font {
1127 self.$member.label_font()
1128 }
1129
1130 fn set_label_font(&mut self, font: $crate::enums::Font) {
1131 self.$member.set_label_font(font)
1132 }
1133
1134 fn label_size(&self) -> i32 {
1135 self.$member.label_size()
1136 }
1137
1138 fn set_label_size(&mut self, sz: i32) {
1139 self.$member.set_label_size(sz)
1140 }
1141
1142 fn label_type(&self) -> $crate::enums::LabelType {
1143 self.$member.label_type()
1144 }
1145
1146 fn set_label_type(&mut self, typ: $crate::enums::LabelType) {
1147 self.$member.set_label_type(typ)
1148 }
1149
1150 fn frame(&self) -> $crate::enums::FrameType {
1151 self.$member.frame()
1152 }
1153
1154 fn set_frame(&mut self, typ: $crate::enums::FrameType) {
1155 self.$member.set_frame(typ)
1156 }
1157
1158 fn changed(&self) -> bool {
1159 self.$member.changed()
1160 }
1161
1162 fn set_changed(&mut self) {
1163 self.$member.set_changed()
1164 }
1165
1166 fn clear_changed(&mut self) {
1167 self.$member.clear_changed()
1168 }
1169
1170 fn align(&self) -> $crate::enums::Align {
1171 self.$member.align()
1172 }
1173
1174 fn set_align(&mut self, align: $crate::enums::Align) {
1175 self.$member.set_align(align)
1176 }
1177
1178 fn parent(&self) -> Option<$crate::group::Group> {
1179 self.$member.parent()
1180 }
1181
1182 fn selection_color(&self) -> $crate::enums::Color {
1183 self.$member.selection_color()
1184 }
1185
1186 fn set_selection_color(&mut self, color: $crate::enums::Color) {
1187 self.$member.set_selection_color(color)
1188 }
1189
1190 fn do_callback(&mut self) {
1191 self.$member.do_callback()
1192 }
1193
1194 fn window(&self) -> Option<Box<dyn WindowExt>> {
1195 self.$member.window()
1196 }
1197
1198 fn top_window(&self) -> Option<Box<dyn WindowExt>> {
1199 self.$member.top_window()
1200 }
1201
1202 fn takes_events(&self) -> bool {
1203 self.$member.takes_events()
1204 }
1205
1206 fn take_focus(&mut self) -> Result<(), FltkError> {
1207 self.$member.take_focus()
1208 }
1209
1210 fn set_visible_focus(&mut self) {
1211 self.$member.set_visible_focus()
1212 }
1213
1214 fn clear_visible_focus(&mut self) {
1215 self.$member.clear_visible_focus()
1216 }
1217
1218 fn visible_focus(&mut self, v: bool) {
1219 self.$member.visible_focus(v)
1220 }
1221
1222 fn has_visible_focus(&self) -> bool {
1223 self.$member.has_visible_focus()
1224 }
1225
1226 fn has_focus(&self) -> bool {
1227 self.$member.has_focus()
1228 }
1229
1230 fn was_deleted(&self) -> bool {
1231 self.$member.was_deleted()
1232 }
1233
1234 fn damage(&self) -> bool {
1235 self.$member.damage()
1236 }
1237
1238 fn set_damage(&mut self, flag: bool) {
1239 self.$member.set_damage(flag)
1240 }
1241
1242 fn damage_type(&self) -> $crate::enums::Damage {
1243 self.$member.damage_type()
1244 }
1245
1246 fn set_damage_type(&mut self, mask: $crate::enums::Damage) {
1247 self.$member.set_damage_type(mask)
1248 }
1249
1250 fn set_damage_area(
1251 &mut self,
1252 mask: $crate::enums::Damage,
1253 x: i32,
1254 y: i32,
1255 w: i32,
1256 h: i32,
1257 ) {
1258 self.$member.set_damage_area(mask, x, y, w, h);
1259 }
1260
1261 fn clear_damage(&mut self) {
1262 self.$member.clear_damage()
1263 }
1264
1265 fn set_when(&mut self, trigger: $crate::enums::When) {
1266 self.$member.set_when(trigger)
1267 }
1268
1269 fn when(&self) -> $crate::enums::When {
1270 self.$member.when()
1271 }
1272
1273 fn as_window(&self) -> Option<Box<dyn WindowExt>> {
1274 self.$member.as_window()
1275 }
1276
1277 fn as_group(&self) -> Option<$crate::group::Group> {
1278 self.$member.as_group()
1279 }
1280
1281 unsafe fn user_data(&self) -> Option<Box<dyn FnMut()>> {
1282 self.$member.user_data()
1283 }
1284
1285 unsafe fn raw_user_data(&self) -> *mut std::os::raw::c_void {
1286 self.$member.raw_user_data()
1287 }
1288
1289 unsafe fn set_raw_user_data(&mut self, data: *mut std::os::raw::c_void) {
1290 self.$member.set_raw_user_data(data)
1291 }
1292
1293 unsafe fn as_widget<W: WidgetBase>(&self) -> W {
1294 self.$member.as_widget()
1295 }
1296
1297 fn visible(&self) -> bool {
1298 self.$member.visible()
1299 }
1300
1301 fn visible_r(&self) -> bool {
1302 self.$member.visible_r()
1303 }
1304
1305 fn is_same<W: WidgetExt>(&self, other: &W) -> bool {
1306 self.$member.is_same(other)
1307 }
1308
1309 fn active(&self) -> bool {
1310 self.$member.active()
1311 }
1312
1313 fn active_r(&self) -> bool {
1314 self.$member.active_r()
1315 }
1316
1317 fn callback(&self) -> Option<Box<dyn FnMut()>> {
1318 self.$member.callback()
1319 }
1320
1321 fn widget_resize(&mut self, x: i32, y: i32, w: i32, h: i32) {
1322 self.$member.widget_resize(x, y, w, h)
1323 }
1324
1325 fn handle_event(&mut self, event: $crate::enums::Event) -> bool {
1326 self.$member.handle_event(event)
1327 }
1328
1329 fn is_derived(&self) -> bool {
1330 self.$member.is_derived()
1331 }
1332 }
1333 };
1334}
1335
1336#[doc(hidden)]
1337#[macro_export]
1338macro_rules! impl_widget_base_via {
1340 ($widget:ty, $base:ty, $member:tt) => {
1341 unsafe impl WidgetBase for $widget {
1342 fn delete(wid: Self) {
1343 <$base>::delete(wid.$member)
1344 }
1345
1346 unsafe fn from_widget_ptr(ptr: $crate::app::WidgetPtr) -> Self {
1347 let $member = <$base>::from_widget_ptr(ptr);
1348 Self {
1349 $member,
1350 ..Default::default()
1351 }
1352 }
1353
1354 unsafe fn from_widget<W: WidgetExt>(w: W) -> Self {
1355 let $member = <$base>::from_widget(w);
1356 Self {
1357 $member,
1358 ..Default::default()
1359 }
1360 }
1361
1362 fn handle<F: FnMut(&mut Self, $crate::enums::Event) -> bool + 'static>(
1363 &mut self,
1364 mut cb: F,
1365 ) {
1366 let mut widget = self.clone();
1367 self.$member.handle(move |_, ev| cb(&mut widget, ev));
1368 }
1369
1370 fn draw<F: FnMut(&mut Self) + 'static>(&mut self, mut cb: F) {
1371 let mut widget = self.clone();
1372 self.$member.draw(move |_| cb(&mut widget))
1373 }
1374
1375 unsafe fn draw_data(&self) -> Option<Box<dyn FnMut()>> {
1376 self.$member.draw_data()
1377 }
1378
1379 unsafe fn handle_data(&self) -> Option<Box<dyn FnMut($crate::enums::Event) -> bool>> {
1380 self.$member.handle_data()
1381 }
1382
1383 fn resize_callback<F: FnMut(&mut Self, i32, i32, i32, i32) + 'static>(
1384 &mut self,
1385 mut cb: F,
1386 ) {
1387 let mut widget = self.clone();
1388 self.$member
1389 .resize_callback(move |_, x, y, w, h| cb(&mut widget, x, y, w, h))
1390 }
1391
1392 unsafe fn assume_derived(&mut self) {
1393 self.assume_derived()
1394 }
1395
1396 fn from_dyn_widget<W: WidgetExt>(w: &W) -> Self {
1397 let $member = <$base>::from_dyn_widget(ptr);
1398 Self {
1399 $member,
1400 ..Default::default()
1401 }
1402 }
1403
1404 fn from_dyn_widget_ptr(w: *mut fltk_sys::widget::Fl_Widget) -> Self {
1405 let $member = <$base>::from_dyn_widget(ptr);
1406 Self {
1407 $member,
1408 ..Default::default()
1409 }
1410 }
1411 }
1412 };
1413}
1414
1415pub use impl_widget_base_via;
1416pub use impl_widget_ext_via;