Widget focus

This commit is contained in:
Silas Bartha 2025-03-27 19:06:53 -04:00
parent 1ceca066d3
commit c8e2ba3c5c

View File

@ -8,13 +8,27 @@ use bevy_terminal_display::{
crossterm::event::{Event, KeyCode, KeyEventKind}, crossterm::event::{Event, KeyCode, KeyEventKind},
input::events::TerminalInputEvent, input::events::TerminalInputEvent,
ratatui::{ ratatui::{
layout::Rect, style::{Color, Modifier, Style}, widgets::{Block, Borders, Clear, HighlightSpacing, List, ListItem, ListState} layout::Rect,
style::{Color, Modifier, Style},
widgets::{Block, Borders, Clear, HighlightSpacing, List, ListItem, ListState},
}, },
widgets::TerminalWidget, widgets::TerminalWidget,
}; };
pub enum MenuControlData<E: bevy::prelude::Event> {
Button {
label: String,
event: E,
},
}
pub struct MenuControl<E: bevy::prelude::Event> {
pub enabled: Arc<AtomicBool>,
pub data: MenuControlData<E>,
}
pub struct MenuWidget<E: bevy::prelude::Event> { pub struct MenuWidget<E: bevy::prelude::Event> {
pub items: Vec<MenuOption<E>>, pub items: Vec<MenuControl<E>>,
pub state: ListState, pub state: ListState,
pub enabled_color: Color, pub enabled_color: Color,
pub disabled_color: Color, pub disabled_color: Color,
@ -37,12 +51,6 @@ impl<E: bevy::prelude::Event> Default for MenuWidget<E> {
} }
} }
pub struct MenuOption<E: bevy::prelude::Event> {
pub enabled: Arc<AtomicBool>,
pub label: String,
pub event: E,
}
impl<E: bevy::prelude::Event + Clone> TerminalWidget for MenuWidget<E> { impl<E: bevy::prelude::Event + Clone> TerminalWidget for MenuWidget<E> {
fn render( fn render(
&mut self, &mut self,
@ -67,7 +75,7 @@ impl<E: bevy::prelude::Event + Clone> TerminalWidget for MenuWidget<E> {
let list = List::new(items) let list = List::new(items)
.block(block) .block(block)
.highlight_style(self.selected_style) .highlight_style(self.selected_style)
.highlight_symbol(">") .highlight_symbol("> ")
.highlight_spacing(HighlightSpacing::Always); .highlight_spacing(HighlightSpacing::Always);
let area = if let Some(area) = &self.area_function { let area = if let Some(area) = &self.area_function {
@ -91,11 +99,15 @@ impl<E: bevy::prelude::Event + Clone> TerminalWidget for MenuWidget<E> {
if let Some(selected) = self.state.selected() { if let Some(selected) = self.state.selected() {
if let Some(item) = self.items.get(selected) { if let Some(item) = self.items.get(selected) {
if item.enabled.load(Ordering::Relaxed) { if item.enabled.load(Ordering::Relaxed) {
commands.send_event(item.event.clone()); match &item.data {
MenuControlData::Button { event, .. } => {
commands.send_event(event.clone());
},
}
} }
} }
} }
}, }
KeyCode::Up => self.state.select_previous(), KeyCode::Up => self.state.select_previous(),
KeyCode::Down => self.state.select_next(), KeyCode::Down => self.state.select_next(),
_ => (), _ => (),
@ -109,10 +121,12 @@ impl<E: bevy::prelude::Event> FromIterator<(&'static str, E)> for MenuWidget<E>
fn from_iter<I: IntoIterator<Item = (&'static str, E)>>(iter: I) -> Self { fn from_iter<I: IntoIterator<Item = (&'static str, E)>>(iter: I) -> Self {
let items = iter let items = iter
.into_iter() .into_iter()
.map(|(label, event)| MenuOption { .map(|(label, event)| MenuControl {
enabled: Arc::new(true.into()), enabled: Arc::new(true.into()),
label: label.into(), data: MenuControlData::Button {
event, label: label.into(),
event,
},
}) })
.collect(); .collect();
Self { Self {
@ -122,8 +136,10 @@ impl<E: bevy::prelude::Event> FromIterator<(&'static str, E)> for MenuWidget<E>
} }
} }
impl<E: bevy::prelude::Event> From<&MenuOption<E>> for ListItem<'_> { impl<E: bevy::prelude::Event> From<&MenuControl<E>> for ListItem<'_> {
fn from(value: &MenuOption<E>) -> Self { fn from(value: &MenuControl<E>) -> Self {
ListItem::new(value.label.clone()) match &value.data {
MenuControlData::Button { label, .. } => ListItem::new(label.clone()),
}
} }
} }