Skip to main content

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}