So I implemented a Focus trait crate:
There I just added a new trait that is both Widget + Focus:
trait FocusableWidget: WidgetRef + Focus {
fn boxed(self) -> Box<dyn FocusableWidget>
where
Self: 'static + Sized,
{
Box::new(self)
}
}
And defined a form which uses it:
#[derive(Focus, FocusContainer)]
pub(crate) struct Form {
pub(crate) children: Vec<Box<dyn FocusableWidget>>,
}
Fill it with some widgets:
let mut form = Form::from_iter([
Label::new("Label 1:").boxed(),
TextBox::new("Text 1").boxed(),
Label::new("Label 2:").boxed(),
TextBox::new("Text 2").boxed(),
Label::new("Label 3:").boxed(),
TextBox::new("Text 3").boxed(),
]);
form.focus_first();
Which is then rendered:
impl WidgetRef for Form {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
let areas = Layout::vertical(vec![Constraint::Length(1); self.children.len()]).split(area);
for (child, area) in zip(self.children.iter(), areas.iter()) {
child.render_ref(*area, buf);
}
}
}
The ability to just slap form fields into a vec like this and be able to produce a rendered form is what I’m talking about when I suggest that WidgetRef is a useful abstaction. This wouldn’t be possible to build with the no Widget traits approach.