use crate::*; /// A component that may contain [Focusable] components. pub trait Focus : Render + Handle { fn focus (&self) -> usize; fn focus_mut (&mut self) -> &mut usize; fn focusable (&self) -> [&dyn Focusable;N]; fn focusable_mut (&mut self) -> [&mut dyn Focusable;N]; fn focused (&self) -> &dyn Focusable { let focus = self.focus(); self.focusable()[focus] } fn focused_mut (&mut self) -> &mut dyn Focusable { let focus = self.focus(); self.focusable_mut()[focus] } fn focus_prev (&mut self) { let focus = self.focus(); self.focus_set(if focus > 0 { focus - 1 } else { N - 1 }); } fn focus_next (&mut self) { let focus = self.focus(); self.focus_set(if focus < N - 1 { focus + 1 } else { 0 }); } fn focus_set (&mut self, focus: usize) { *self.focus_mut() = focus; let focusable = self.focusable_mut(); for index in 0..N { focusable[index].set_focused(index == focus); } } } /// A component that may be focused. pub trait Focusable: Render + Handle { fn is_focused (&self) -> bool; fn set_focused (&mut self, focused: bool); } impl, E: Engine> Focusable for Option where Option: Render { fn is_focused (&self) -> bool { match self { Some(focusable) => focusable.is_focused(), None => false } } fn set_focused (&mut self, focused: bool) { if let Some(focusable) = self { focusable.set_focused(focused) } } } /// Implement the [Focus] trait for a component. #[macro_export] macro_rules! focus { ($struct:ident ($focus:ident) : $count:expr => [ $($focusable:ident),* ]) => { impl Focus<$count, E> for $struct { fn focus (&self) -> usize { self.$focus } fn focus_mut (&mut self) -> &mut usize { &mut self.$focus } fn focusable (&self) -> [&dyn Focusable;$count] { [ $(&self.$focusable as &dyn Focusable,)* ] } fn focusable_mut (&mut self) -> [&mut dyn Focusable;$count] { [ $(&mut self.$focusable as &mut dyn Focusable,)* ] } } } } /// Implement the [Focusable] trait for a component. #[macro_export] macro_rules! focusable { ($struct:ident) => { focusable!($struct (focused)); }; ($struct:ident ($focused:ident)) => { impl Focusable for $struct { fn is_focused (&self) -> bool { self.$focused } fn set_focused (&mut self, focused: bool) { self.$focused = focused } } } }