Skip to main content

agpu/widget/
mod.rs

1//! Widget library for agpu — reusable UI components.
2//!
3//! Each widget implements the [`Widget`] trait and is fully discoverable
4//! via the ontology system. Widgets render through the [`Painter`] trait
5//! and register hitboxes for event routing.
6
7mod button;
8mod checkbox;
9mod list;
10mod menu;
11mod modal;
12mod progress;
13mod select;
14mod slider;
15mod tabs;
16mod text_area;
17mod text_input;
18mod tooltip;
19mod tree;
20
21pub use button::Button;
22pub use checkbox::{Checkbox, Radio};
23pub use list::{List, Table};
24pub use menu::Menu;
25pub use modal::Modal;
26pub use progress::ProgressBar;
27pub use select::Select;
28pub use slider::Slider;
29pub use tabs::{Panel, Tabs};
30pub use text_area::TextArea;
31pub use text_input::TextInput;
32pub use tooltip::Tooltip;
33pub use tree::TreeView;
34
35use crate::core::Rect;
36use crate::ontology::{Discoverable, UiNode};
37use crate::paint::Painter;
38
39/// Trait implemented by all widgets.
40pub trait Widget: Discoverable {
41    /// Render the widget into the given area using the painter.
42    fn draw(&self, painter: &mut dyn Painter, area: Rect);
43
44    /// Build a UI node for ontology registration.
45    fn ui_node(&self) -> UiNode;
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn button_draw_does_not_panic() {
54        let btn = Button::new("click_me", "Click");
55        let mut painter = crate::paint::NullPainter;
56        btn.draw(&mut painter, Rect::new(0.0, 0.0, 100.0, 40.0));
57    }
58
59    #[test]
60    fn text_input_draw_does_not_panic() {
61        let input = TextInput::new("input_1");
62        let mut painter = crate::paint::NullPainter;
63        input.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 30.0));
64    }
65
66    #[test]
67    fn checkbox_draw_does_not_panic() {
68        let cb = Checkbox::new("cb_1", "Accept", false);
69        let mut painter = crate::paint::NullPainter;
70        cb.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 24.0));
71    }
72
73    #[test]
74    fn radio_draw_does_not_panic() {
75        let radio = Radio::new("r_1", "Option A", false);
76        let mut painter = crate::paint::NullPainter;
77        radio.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 24.0));
78    }
79
80    #[test]
81    fn slider_draw_does_not_panic() {
82        let slider = Slider::new("s_1", 0.5, 0.0, 1.0);
83        let mut painter = crate::paint::NullPainter;
84        slider.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 24.0));
85    }
86
87    #[test]
88    fn select_draw_does_not_panic() {
89        let select = Select::new("sel_1", vec!["A".into(), "B".into()]);
90        let mut painter = crate::paint::NullPainter;
91        select.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 30.0));
92    }
93
94    #[test]
95    fn list_draw_does_not_panic() {
96        let list = List::new("list_1", vec!["Item 1".into(), "Item 2".into()]);
97        let mut painter = crate::paint::NullPainter;
98        list.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 100.0));
99    }
100
101    #[test]
102    fn table_draw_does_not_panic() {
103        let table = Table::new(
104            "table_1",
105            vec!["Name".into(), "Age".into()],
106            vec![vec!["Alice".into(), "30".into()]],
107        );
108        let mut painter = crate::paint::NullPainter;
109        table.draw(&mut painter, Rect::new(0.0, 0.0, 400.0, 200.0));
110    }
111
112    #[test]
113    fn tabs_draw_does_not_panic() {
114        let tabs = Tabs::new("tabs_1", vec!["Tab A".into(), "Tab B".into()], 0);
115        let mut painter = crate::paint::NullPainter;
116        tabs.draw(&mut painter, Rect::new(0.0, 0.0, 400.0, 300.0));
117    }
118
119    #[test]
120    fn modal_draw_does_not_panic() {
121        let modal = Modal::new("modal_1", "Confirm?", true);
122        let mut painter = crate::paint::NullPainter;
123        modal.draw(&mut painter, Rect::new(0.0, 0.0, 800.0, 600.0));
124    }
125
126    #[test]
127    fn tree_draw_does_not_panic() {
128        let tree = TreeView::new("tree_1", tree::TreeNode::new("root", "Root"));
129        let mut painter = crate::paint::NullPainter;
130        tree.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 200.0));
131    }
132
133    #[test]
134    fn progress_draw_does_not_panic() {
135        let bar = ProgressBar::new("prog_1", 0.75);
136        let mut painter = crate::paint::NullPainter;
137        bar.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 20.0));
138    }
139
140    #[test]
141    fn menu_draw_does_not_panic() {
142        let menu = Menu::new("menu_1", vec![menu::MenuItem::item("open", "Open")]);
143        let mut painter = crate::paint::NullPainter;
144        menu.draw(&mut painter, Rect::new(0.0, 0.0, 200.0, 300.0));
145    }
146
147    #[test]
148    fn text_area_draw_does_not_panic() {
149        let ta = TextArea::new("ta_1");
150        let mut painter = crate::paint::NullPainter;
151        ta.draw(&mut painter, Rect::new(0.0, 0.0, 300.0, 200.0));
152    }
153
154    #[test]
155    fn tooltip_draw_does_not_panic() {
156        let tt = Tooltip::new("tt_1", "Help text");
157        let mut painter = crate::paint::NullPainter;
158        tt.draw(&mut painter, Rect::new(100.0, 100.0, 150.0, 30.0));
159    }
160}