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_text2(&w.label(), 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);
39
40/// An alias exposing the Widget tracker
41pub type WidgetTrackerPtr = *mut fltk_sys::fl::Fl_Widget_Tracker;
42
43/// Widget Tracker Wrapper
44#[doc(hidden)]
45pub type WidgetTrackerWrapper = std::rc::Rc<WidgetTrackerPtr>;
46
47/// Widget Tracker
48#[derive(Debug, Clone)]
49pub struct WidgetTracker {
50    inner: WidgetTrackerWrapper,
51}
52
53#[cfg(not(feature = "single-threaded"))]
54unsafe impl Send for WidgetTracker {}
55
56#[cfg(not(feature = "single-threaded"))]
57unsafe impl Sync for WidgetTracker {}
58
59impl Drop for WidgetTracker {
60    fn drop(&mut self) {
61        if WidgetTrackerWrapper::strong_count(&self.inner) == 1 {
62            unsafe {
63                fltk_sys::fl::Fl_Widget_Tracker_delete(*self.inner);
64            }
65        }
66    }
67}
68
69impl WidgetTracker {
70    /// Creates a new widget tracker
71    pub fn new(w: *mut Fl_Widget) -> Self {
72        let ptr = unsafe { fltk_sys::fl::Fl_Widget_Tracker_new(w as _) };
73        assert!(!ptr.is_null());
74        Self {
75            inner: WidgetTrackerWrapper::new(ptr),
76        }
77    }
78
79    /// Checks if the wrapped widget was deleted
80    pub fn deleted(&self) -> bool {
81        unsafe { fltk_sys::fl::Fl_Widget_Tracker_deleted(*self.inner) != 0 }
82    }
83
84    /// Gets the wrapped widget
85    pub fn widget(&self) -> *mut Fl_Widget {
86        let w = unsafe { fltk_sys::fl::Fl_Widget_Tracker_widget(*self.inner) };
87        assert!(!w.is_null());
88        w as _
89    }
90}