slt/context/widget.rs
1/// Trait for creating custom widgets.
2///
3/// Implement this trait to build reusable, composable widgets with full access
4/// to the [`Context`] API — focus, events, theming, layout, and mouse interaction.
5///
6/// # Examples
7///
8/// A simple rating widget:
9///
10/// ```no_run
11/// use slt::{Context, Widget, Color};
12///
13/// struct Rating {
14/// value: u8,
15/// max: u8,
16/// }
17///
18/// impl Rating {
19/// fn new(value: u8, max: u8) -> Self {
20/// Self { value, max }
21/// }
22/// }
23///
24/// impl Widget for Rating {
25/// type Response = bool;
26///
27/// fn ui(&mut self, ui: &mut Context) -> bool {
28/// let focused = ui.register_focusable();
29/// let mut changed = false;
30///
31/// if focused {
32/// if ui.key('+') && self.value < self.max {
33/// self.value += 1;
34/// changed = true;
35/// }
36/// if ui.key('-') && self.value > 0 {
37/// self.value -= 1;
38/// changed = true;
39/// }
40/// }
41///
42/// let stars: String = (0..self.max).map(|i| {
43/// if i < self.value { '★' } else { '☆' }
44/// }).collect();
45///
46/// let color = if focused { Color::Yellow } else { Color::White };
47/// ui.styled(stars, slt::Style::new().fg(color));
48///
49/// changed
50/// }
51/// }
52///
53/// fn main() -> std::io::Result<()> {
54/// let mut rating = Rating::new(3, 5);
55/// slt::run(|ui| {
56/// if ui.key('q') { ui.quit(); }
57/// ui.text("Rate this:");
58/// ui.widget(&mut rating);
59/// })
60/// }
61/// ```
62pub trait Widget {
63 /// The value returned after rendering. Use `()` for widgets with no return,
64 /// `bool` for widgets that report changes, or [`Response`] for click/hover.
65 type Response;
66
67 /// Render the widget into the given context.
68 ///
69 /// Use [`Context::register_focusable`] to participate in Tab focus cycling,
70 /// [`Context::key`] / [`Context::key_code`] to handle keyboard input,
71 /// and [`Context::interaction`] to detect clicks and hovers.
72 fn ui(&mut self, ctx: &mut Context) -> Self::Response;
73}