///|
/// Focus management for TUI applications
///|
/// Focus manager for handling focus state and navigation
pub struct FocusManager {
mut focus : FocusState
mut mode : InputMode
focusable_ids : Array[String]
}
///|
/// Create a new focus manager
pub fn FocusManager::new() -> FocusManager {
{ focus: FocusState::None, mode: InputMode::Normal, focusable_ids: [] }
}
///|
/// Register a focusable component ID
pub fn FocusManager::register(self : FocusManager, id : String) -> Unit {
if !self.focusable_ids.contains(id) {
self.focusable_ids.push(id)
}
}
///|
/// Unregister a focusable component ID
pub fn FocusManager::unregister(self : FocusManager, id : String) -> Unit {
let idx = self.focusable_ids.search(id)
match idx {
Some(i) => {
let _ = self.focusable_ids.remove(i)
}
None => ()
}
}
///|
/// Set focus to a specific component
pub fn FocusManager::focus(self : FocusManager, id : String) -> Unit {
self.focus = FocusState::Focused(id)
}
///|
/// Remove focus (blur)
pub fn FocusManager::blur(self : FocusManager) -> Unit {
self.focus = FocusState::None
}
///|
/// Check if a component is currently focused
pub fn FocusManager::is_focused(self : FocusManager, id : String) -> Bool {
match self.focus {
FocusState::Focused(focused_id) => focused_id == id
FocusState::None => false
}
}
///|
/// Get the currently focused component ID
pub fn FocusManager::get_focused(self : FocusManager) -> String? {
match self.focus {
FocusState::Focused(id) => Some(id)
FocusState::None => None
}
}
///|
/// Focus the next component in the focusable list (Tab navigation)
pub fn FocusManager::focus_next(self : FocusManager) -> Unit {
if self.focusable_ids.length() == 0 {
return
}
match self.focus {
FocusState::None => self.focus = FocusState::Focused(self.focusable_ids[0])
FocusState::Focused(current_id) => {
let idx = self.focusable_ids.search(current_id)
match idx {
Some(i) => {
let next_idx = (i + 1) % self.focusable_ids.length()
self.focus = FocusState::Focused(self.focusable_ids[next_idx])
}
None => self.focus = FocusState::Focused(self.focusable_ids[0])
}
}
}
}
///|
/// Focus the previous component in the focusable list (Shift+Tab navigation)
pub fn FocusManager::focus_prev(self : FocusManager) -> Unit {
if self.focusable_ids.length() == 0 {
return
}
match self.focus {
FocusState::None =>
self.focus = FocusState::Focused(
self.focusable_ids[self.focusable_ids.length() - 1],
)
FocusState::Focused(current_id) => {
let idx = self.focusable_ids.search(current_id)
match idx {
Some(i) => {
let prev_idx = if i == 0 {
self.focusable_ids.length() - 1
} else {
i - 1
}
self.focus = FocusState::Focused(self.focusable_ids[prev_idx])
}
None =>
self.focus = FocusState::Focused(
self.focusable_ids[self.focusable_ids.length() - 1],
)
}
}
}
}
///|
/// Enter editing mode
pub fn FocusManager::start_editing(self : FocusManager) -> Unit {
self.mode = InputMode::Editing
}
///|
/// Exit editing mode
pub fn FocusManager::stop_editing(self : FocusManager) -> Unit {
self.mode = InputMode::Normal
}
///|
/// Check if currently in editing mode
pub fn FocusManager::is_editing(self : FocusManager) -> Bool {
match self.mode {
InputMode::Editing => true
InputMode::Normal => false
}
}
///|
/// Get current input mode
pub fn FocusManager::get_mode(self : FocusManager) -> InputMode {
self.mode
}
///|
/// Get the number of focusable elements
pub fn FocusManager::focusable_count(self : FocusManager) -> Int {
self.focusable_ids.length()
}