fltk/macros/
widget.rs

1#[doc(hidden)]
2#[macro_export]
3/// Implements WidgetExt
4macro_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]
617/// Implements WidgetBase
618macro_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                    // if cfg!(target_os = "macos") && self.as_window().is_some() {
649                    //     assert!(self.takes_events());
650                    // }
651                    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: ![<$flname _from_derived_dyn_ptr>](w as _).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                /// Creates a new widget, takes an x, y coordinates, as well as a width and height, plus a title
826                /// # Arguments
827                /// * `x` - The x coordinate in the screen
828                /// * `y` - The y coordinate in the screen
829                /// * `width` - The width of the widget
830                /// * `heigth` - The height of the widget
831                /// * `title` - The title or label of the widget
832                ///
833                /// To use dynamic strings use `with_label(self, &str)` or `set_label(&mut self, &str)`.
834                /// labels support special symbols preceded by an `@` [sign](https://www.fltk.org/doc-1.3/symbols.png)
835                /// and for the [associated formatting](https://www.fltk.org/doc-1.3/common.html).
836                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                /// Constructs a widget with the size of its parent
879                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]
889/// Implements WidgetType
890macro_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]
911/// Implements WidgetExt via a member
912macro_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]
1338/// Implements WidgetBase via a member
1339macro_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;