Skip to main content

bexa_ui_core/
lib.rs

1pub mod framework;
2pub mod icons;
3pub mod renderer;
4pub mod signal;
5pub mod theme;
6pub mod tree;
7pub mod widgets;
8
9pub use framework::{DrawContext, EventContext, Widget};
10pub use renderer::{QuadCommand, Renderer, TextCommand};
11pub use signal::{Signal, SetSignal, IntoSignal, create_signal};
12pub use theme::Theme;
13pub use tree::{
14    build_taffy, clear_active_widgets, collect_focus_paths, dispatch_event, dispatch_scroll,
15    draw_widgets, handle_scrollbar_event, release_scrollbar_drag, scroll_root, sync_styles,
16    try_start_scrollbar_drag, update_widget_measures, widget_mut_at_path, WidgetNode,
17};
18pub use widgets::{Button, Checkbox, Container, Flex, Icon, Label, RadioButton, radio_group, Select, TextInput};
19
20#[cfg(feature = "terminal")]
21pub use widgets::Terminal;
22
23// Re-export text types so downstream crates don't need glyphon directly
24pub use glyphon::Metrics;
25pub use glyphon::cosmic_text::Align;
26
27use std::sync::{Arc, Mutex};
28
29/// Request to open a new window from within a widget callback.
30pub struct WindowRequest {
31    pub title: String,
32    pub width: u32,
33    pub height: u32,
34    pub root: WidgetNode,
35    pub theme: Theme,
36}
37
38/// Shared handle for widgets to request new windows.
39pub type WindowRequests = Arc<Mutex<Vec<WindowRequest>>>;
40
41/// Create a new `WindowRequests` handle.
42pub fn create_window_requests() -> WindowRequests {
43    Arc::new(Mutex::new(Vec::new()))
44}
45
46/// Declarative UI macro for building widget trees.
47///
48/// # Syntax
49/// ```ignore
50/// ui! {
51///     Container::new() => {
52///         Flex::row(12.0) => { btn_a, btn_b },
53///         label,
54///     }
55/// }
56/// ```
57///
58/// - `widget => { children... }` — container with children
59/// - `widget` — leaf node (no children), automatically wrapped
60/// - Children can be bare widgets or nested `container => { ... }` expressions
61/// - `ui!(widget)` still works for explicit leaf wrapping
62#[macro_export]
63macro_rules! ui {
64    // Container with children: Widget => { child, child, ... }
65    ( $widget:expr => { $( $child:tt )* } ) => {
66        $crate::WidgetNode::new($widget, $crate::ui_items![ $( $child )* ])
67    };
68
69    // Leaf: Widget (no children)
70    ( $widget:expr ) => {
71        $crate::WidgetNode::new($widget, vec![])
72    };
73}
74
75/// Internal macro to parse a comma-separated list of UI items.
76/// Each item is either `widget => { children }` or a bare expression.
77#[macro_export]
78#[doc(hidden)]
79macro_rules! ui_items {
80    // Empty
81    () => { vec![] };
82
83    // Container item: expr => { ... }, rest...
84    ( $widget:expr => { $( $inner:tt )* } , $( $rest:tt )* ) => {{
85        let mut v = vec![ $crate::ui!( $widget => { $( $inner )* } ) ];
86        v.extend( $crate::ui_items![ $( $rest )* ] );
87        v
88    }};
89
90    // Container item: expr => { ... } (last, no trailing comma)
91    ( $widget:expr => { $( $inner:tt )* } ) => {
92        vec![ $crate::ui!( $widget => { $( $inner )* } ) ]
93    };
94
95    // Leaf item: expr, rest...
96    ( $widget:expr , $( $rest:tt )* ) => {{
97        let mut v = vec![ $crate::ui!( $widget ) ];
98        v.extend( $crate::ui_items![ $( $rest )* ] );
99        v
100    }};
101
102    // Leaf item: expr (last, no trailing comma)
103    ( $widget:expr ) => {
104        vec![ $crate::ui!( $widget ) ]
105    };
106}