fltk/
widget.rs

1//! Basic empty widget
2//!
3//! **Multithreaded** applications can call widget methods from non-ui
4//! threads, but will need to call [`app::awake()`](`crate::app::awake`) to awaken
5//! the ui thread's event loop.
6
7use crate::prelude::*;
8use crate::utils::FlString;
9use fltk_sys::widget::*;
10use std::ffi::{CStr, CString};
11
12/// An empty widget. Instantiating a Widget requires that you at least add a draw callback for it to show anything
13/// ```rust,no_run
14/// use fltk::{prelude::*, *};
15/// fn main() {
16///     let a = app::App::default();
17///     let mut win = window::Window::default();
18///     let mut wid = widget::Widget::default();
19///     win.end();
20///     win.show();
21///     wid.draw(|w| {
22///         draw::draw_box(w.frame(), w.x(), w.y(), w.w(), w.h(), w.color());
23///         draw::set_draw_color(enums::Color::Black); // for the text
24///         draw::set_font(enums::Font::Helvetica, app::font_size());
25///         draw::draw_text_boxed(&w.label().unwrap(), w.x(), w.y(), w.w(), w.h(), w.align());
26///     });
27///     a.run().unwrap();
28/// }
29/// ```
30#[derive(Debug)]
31pub struct Widget {
32    inner: crate::widget::WidgetTracker,
33    is_derived: bool,
34}
35
36crate::macros::widget::impl_widget_ext!(Widget, Fl_Widget);
37crate::macros::widget::impl_widget_base!(Widget, Fl_Widget);
38crate::macros::widget::impl_widget_default!(Widget, Fl_Widget);
39
40/// An alias exposing the Widget tracker
41pub type WidgetTrackerPtr = *mut fltk_sys::fl::Fl_Widget_Tracker;
42
43/// Widget Tracker Wrapper
44pub type WidgetTrackerWrapper = std::rc::Rc<WidgetTrackerPtr>;
45
46/// Widget Tracker
47#[derive(Debug, Clone)]
48pub struct WidgetTracker {
49    inner: WidgetTrackerWrapper,
50}
51
52#[cfg(not(feature = "single-threaded"))]
53unsafe impl Send for WidgetTracker {}
54
55#[cfg(not(feature = "single-threaded"))]
56unsafe impl Sync for WidgetTracker {}
57
58impl Drop for WidgetTracker {
59    fn drop(&mut self) {
60        if WidgetTrackerWrapper::strong_count(&self.inner) == 1 {
61            unsafe {
62                fltk_sys::fl::Fl_Widget_Tracker_delete(*self.inner);
63            }
64        }
65    }
66}
67
68impl WidgetTracker {
69    /// Creates a new widget tracker
70    pub fn new(w: *mut Fl_Widget) -> Self {
71        let ptr = unsafe { fltk_sys::fl::Fl_Widget_Tracker_new(w as _) };
72        assert!(!ptr.is_null());
73        Self {
74            inner: WidgetTrackerWrapper::new(ptr),
75        }
76    }
77
78    /// Checks if the wrapped widget was deleted
79    pub fn deleted(&self) -> bool {
80        unsafe { fltk_sys::fl::Fl_Widget_Tracker_deleted(*self.inner) != 0 }
81    }
82
83    /// Gets the wrapped widget
84    pub fn widget(&self) -> *mut Fl_Widget {
85        let w = unsafe { fltk_sys::fl::Fl_Widget_Tracker_widget(*self.inner) };
86        assert!(!w.is_null());
87        w as _
88    }
89}