Skip to main content

azul_layout/widgets/
mod.rs

1//! Built-in widgets for the Azul GUI system
2
3/// Implements `Display, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Hash`
4/// for a Callback with a `.cb` field.
5///
6/// This is necessary to work around for https://github.com/rust-lang/rust/issues/54508
7///
8/// # Host-invoker plumbing for managed-FFI bindings
9///
10/// Widget callbacks have varying shapes — some are
11/// `(RefAny, CallbackInfo) -> Update` (Button), others add a state
12/// struct (CheckBox/Tab/etc.), a few have two extras (ListView). The
13/// macro therefore does **not** auto-emit an `impl_managed_callback!`
14/// invocation; per-widget files apply it themselves with the right
15/// extras list. The base invocation still produces the standard
16/// `Display`/`Debug`/`Clone`/`From<CallbackType>`/`From<Callback>` impls
17/// that all widget callbacks share.
18#[macro_export]
19macro_rules! impl_widget_callback {
20    (
21        $callback_wrapper:ident,
22        $option_callback_wrapper:ident,
23        $callback_value:ident,
24        $callback_ty:ident
25    ) => {
26        #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
27        #[repr(C)]
28        pub struct $callback_wrapper {
29            pub refany: RefAny,
30            pub callback: $callback_value,
31        }
32
33        #[repr(C)]
34        pub struct $callback_value {
35            pub cb: $callback_ty,
36            /// For FFI: stores the foreign callable (e.g., PyFunction)
37            /// Native Rust code sets this to None
38            pub ctx: azul_core::refany::OptionRefAny,
39        }
40
41        azul_css::impl_option!(
42            $callback_wrapper,
43            $option_callback_wrapper,
44            copy = false,
45            [Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
46        );
47
48        impl $callback_value {
49            /// Create a new callback with just a function pointer (for native Rust code)
50            pub fn create<I: Into<$callback_value>>(cb: I) -> $callback_value {
51                cb.into()
52            }
53        }
54
55        impl ::core::fmt::Display for $callback_value {
56            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
57                write!(f, "{:?}", self)
58            }
59        }
60
61        impl ::core::fmt::Debug for $callback_value {
62            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
63                let callback = stringify!($callback_value);
64                write!(f, "{} @ 0x{:x}", callback, self.cb as *const () as usize)
65            }
66        }
67
68        impl Clone for $callback_value {
69            fn clone(&self) -> Self {
70                $callback_value {
71                    cb: self.cb.clone(),
72                    ctx: self.ctx.clone(),
73                }
74            }
75        }
76
77        impl core::hash::Hash for $callback_value {
78            fn hash<H>(&self, state: &mut H)
79            where
80                H: ::core::hash::Hasher,
81            {
82                state.write_usize(self.cb as *const () as usize);
83            }
84        }
85
86        impl PartialEq for $callback_value {
87            fn eq(&self, rhs: &Self) -> bool {
88                self.cb as *const () as usize == rhs.cb as usize
89            }
90        }
91
92        impl PartialOrd for $callback_value {
93            fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
94                Some((self.cb as *const () as usize).cmp(&(other.cb as usize)))
95            }
96        }
97
98        impl Ord for $callback_value {
99            fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
100                (self.cb as *const () as usize).cmp(&(other.cb as usize))
101            }
102        }
103
104        impl Eq for $callback_value {}
105
106        /// Allow creating callback from a raw function pointer
107        /// Sets callable to None (for native Rust/C usage)
108        impl From<$callback_ty> for $callback_value {
109            fn from(cb: $callback_ty) -> $callback_value {
110                $callback_value {
111                    cb,
112                    ctx: azul_core::refany::OptionRefAny::None,
113                }
114            }
115        }
116
117        /// Allow creating widget callback from a generic Callback
118        /// This enables Python/FFI code to pass generic callbacks to widget methods
119        impl From<crate::callbacks::Callback> for $callback_value {
120            fn from(cb: crate::callbacks::Callback) -> $callback_value {
121                $callback_value {
122                    cb: unsafe { core::mem::transmute(cb.cb) },
123                    ctx: cb.ctx,
124                }
125            }
126        }
127    };
128}
129
130/// Button widget
131pub mod button;
132/// Checkbox widget
133pub mod check_box;
134/// Box displaying a color which opens a color picker dialog on being clicked
135pub mod color_input;
136/// File input widget
137pub mod file_input;
138/// Label widget (centered text)
139pub mod label;
140/// Drop-down select widget
141pub mod drop_down;
142/// Frame container widget
143pub mod frame;
144/// List view widget
145pub mod list_view;
146/// Shared core for the video-ish widgets (camera/screencap/video): the
147/// `VideoFrame` type + the GL-texture `present_frame` writeback. See
148/// `capture_common.rs`.
149pub mod capture_common;
150/// Camera-preview widget (P6) — a "dumb widget" owning a background capture
151/// thread + a GL-texture ImageRef; no camera logic in core. Same RefAny-
152/// dataset + merge-callback design as the map widget. See `camera.rs`.
153pub mod camera;
154/// Screen-capture widget (P6) — identical "dumb widget" architecture to the
155/// camera widget, capturing a display/window instead. See `screencap.rs`.
156pub mod screencap;
157/// Video-playback widget (P6) — same "dumb widget" architecture, decoding a
158/// video source (vk-video) into a GL texture. See `video.rs`.
159pub mod video;
160/// Microphone-capture widget (P7) — same "dumb widget" architecture as the
161/// capture widgets, audio instead of video (no GL): a background thread feeds
162/// each `AudioFrame` to the user's `on_frame` hook. See `microphone.rs`.
163pub mod microphone;
164/// Map widget — MVT tile + MapCSS → SVG → DOM (AzulMaps goal app, P3).
165/// Cache lives in a dataset RefAny owned by a merge callback so it
166/// survives relayout. See `layout/src/widgets/map.rs` for the design.
167pub mod map;
168/// Node graph widget
169pub mod node_graph;
170/// Same as text input, but only allows numeric input
171pub mod number_input;
172/// Progress bar widget
173pub mod progressbar;
174/// Ribbon widget
175pub mod ribbon;
176/// Tab container widgets
177pub mod tabs;
178/// Single line text input widget
179pub mod text_input;
180/// Titlebar widget for custom window chrome
181pub mod titlebar;
182/// Tree view widget
183pub mod tree_view;
184// /// Spreadsheet (virtualized view) widget
185// pub mod spreadsheet;
186// /// Slider widget
187// pub mod slider;
188// /// Multi-line text input
189// pub mod text_edit;