use super::event::{Event, EventFlow, KeyCode};
#[derive(Clone, Debug, Default)]
pub struct FocusRegistry {
order: Vec<String>,
focused: Option<String>,
owner: Option<String>,
}
impl FocusRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn begin_frame(&mut self) {
self.order.clear();
}
pub fn register(&mut self, id: impl Into<String>) {
let id = id.into();
if self.focused.is_none() {
self.focused = Some(id.clone());
}
self.order.push(id);
}
pub fn set_owner(&mut self, id: impl Into<String>) {
self.owner = Some(id.into());
}
pub fn clear_owner(&mut self) {
self.owner = None;
}
pub fn active(&self) -> Option<&str> {
self.owner.as_deref().or(self.focused.as_deref())
}
pub fn is_active(&self, id: &str) -> bool {
self.active() == Some(id)
}
pub fn is_focused(&self, id: &str) -> bool {
self.focused.as_deref() == Some(id)
}
fn advance(&mut self, delta: isize) {
if self.order.is_empty() {
return;
}
let len = self.order.len() as isize;
let current = self
.focused
.as_ref()
.and_then(|f| self.order.iter().position(|id| id == f))
.map(|p| p as isize)
.unwrap_or(0);
let next = ((current + delta) % len + len) % len;
self.focused = Some(self.order[next as usize].clone());
}
pub fn handle(&mut self, event: &Event) -> EventFlow {
if self.owner.is_some() {
return EventFlow::Ignored;
}
let Event::Key(k) = event else {
return EventFlow::Ignored;
};
match k.code {
KeyCode::Tab if k.plain() => {
self.advance(1);
EventFlow::Consumed
}
KeyCode::BackTab => {
self.advance(-1);
EventFlow::Consumed
}
_ => EventFlow::Ignored,
}
}
}