use ratatui::style::{Color, Modifier, Style};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct FocusId(pub u32);
impl FocusId {
pub fn new(id: u32) -> Self {
Self(id)
}
pub fn id(&self) -> u32 {
self.0
}
}
impl From<u32> for FocusId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl From<usize> for FocusId {
fn from(id: usize) -> Self {
Self(id as u32)
}
}
pub trait Focusable {
fn focus_id(&self) -> FocusId;
fn is_focused(&self) -> bool;
fn set_focused(&mut self, focused: bool);
fn focused_style(&self) -> Style {
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD)
}
fn unfocused_style(&self) -> Style {
Style::default().fg(Color::White)
}
fn current_style(&self) -> Style {
if self.is_focused() {
self.focused_style()
} else {
self.unfocused_style()
}
}
fn can_focus(&self) -> bool {
true
}
fn tab_order(&self) -> u32 {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestWidget {
focus_id: FocusId,
focused: bool,
enabled: bool,
tab_order: u32,
}
impl TestWidget {
fn new(id: u32) -> Self {
Self {
focus_id: FocusId::new(id),
focused: false,
enabled: true,
tab_order: 0,
}
}
}
impl Focusable for TestWidget {
fn focus_id(&self) -> FocusId {
self.focus_id
}
fn is_focused(&self) -> bool {
self.focused
}
fn set_focused(&mut self, focused: bool) {
self.focused = focused;
}
fn can_focus(&self) -> bool {
self.enabled
}
fn tab_order(&self) -> u32 {
self.tab_order
}
}
#[test]
fn test_focus_id_creation() {
let id = FocusId::new(42);
assert_eq!(id.id(), 42);
let id_from_u32: FocusId = 100u32.into();
assert_eq!(id_from_u32.id(), 100);
let id_from_usize: FocusId = 200usize.into();
assert_eq!(id_from_usize.id(), 200);
}
#[test]
fn test_focus_state() {
let mut widget = TestWidget::new(1);
assert!(!widget.is_focused());
widget.set_focused(true);
assert!(widget.is_focused());
widget.set_focused(false);
assert!(!widget.is_focused());
}
#[test]
fn test_current_style() {
let mut widget = TestWidget::new(1);
let style = widget.current_style();
assert_eq!(style, widget.unfocused_style());
widget.set_focused(true);
let style = widget.current_style();
assert_eq!(style, widget.focused_style());
}
#[test]
fn test_can_focus() {
let mut widget = TestWidget::new(1);
assert!(widget.can_focus());
widget.enabled = false;
assert!(!widget.can_focus());
}
#[test]
fn test_tab_order() {
let mut widget = TestWidget::new(1);
assert_eq!(widget.tab_order(), 0);
widget.tab_order = 5;
assert_eq!(widget.tab_order(), 5);
}
}