Files
rubbs/lib/bbs/focus_manager.rb
2026-05-12 22:15:07 +02:00

77 lines
1.5 KiB
Ruby

# frozen_string_literal: true
module BBS
# Tracks which widget within a Container currently has focus.
# Tab / Shift-Tab cycle through its focusable descendants.
class FocusManager
attr_reader :focused
def initialize(container)
@container = container
@focused = nil
focus_first
end
def candidates
@container.focusable_descendants.select { |w| w.enabled }
end
def focus_first
first = candidates.first
set_focus(first)
end
def focus(widget)
set_focus(widget) if widget && widget.focusable? && widget.enabled
end
def next_focus
list = candidates
return if list.empty?
idx = list.index(@focused) || -1
set_focus(list[(idx + 1) % list.size])
end
def prev_focus
list = candidates
return if list.empty?
idx = list.index(@focused) || 0
set_focus(list[(idx - 1) % list.size])
end
def handle_focus_key(event)
return false unless event.key?
case event.key
when :tab
next_focus
true
when :shift_tab
prev_focus
true
else
false
end
end
def dispatch(event)
return nil unless @focused
@focused.handle_event(event)
end
private
def set_focus(widget)
return if widget == @focused
if @focused
@focused.focused = false
@focused.on_blur
end
@focused = widget
if widget
widget.focused = true
widget.on_focus
end
end
end
end