use core::marker::PhantomData;
use bevy_ecs::prelude::*;
use bevy_input_focus::tab_navigation::TabGroup;
use bevy_reflect::Reflect;
use bevy_scene::prelude::*;
use bevy_ui::{px, widget::Text, FlexDirection, Node};
use bevy_ui_widgets::Activate;
use crate::controls::FeathersButton;
#[derive(SceneComponent, FromTemplate)]
#[scene(VirtualKeyboardProps<T>)]
#[derive(Reflect)]
#[reflect(Component)]
pub struct VirtualKeyboard<T: AsRef<str> + Clone + Send + Sync + 'static>(PhantomData<fn() -> T>);
pub struct VirtualKeyboardProps<T> {
pub keys: Vec<Vec<T>>,
}
impl<T> Default for VirtualKeyboardProps<T> {
fn default() -> Self {
Self {
keys: Default::default(),
}
}
}
impl<T: AsRef<str> + Clone + Send + Sync + 'static> VirtualKeyboard<T> {
fn scene(props: VirtualKeyboardProps<T>) -> impl Scene {
let keys = Vec::from_iter(props.keys.into_iter().map(move |row| {
let key_row = Vec::from_iter(row.into_iter().map(move |key| {
let key_clone = key.clone();
bsn! {
@FeathersButton
Node {
flex_grow: 1.0,
}
on(move |activate: On<Activate>,
mut commands: Commands,
query: Query<&ChildOf>|
-> Result {
let virtual_keyboard =
query.get(query.get(activate.entity)?.parent())?.parent();
commands.trigger(VirtualKeyPressed {
entity: virtual_keyboard,
key: key.clone(),
});
Ok(())
})
Children [
Text::new(key_clone.as_ref())
]
}
}));
bsn! {
Node {
flex_direction: FlexDirection::Row,
column_gap: px(4),
}
Children [
{key_row}
]
}
}));
bsn! {
Node {
flex_direction: FlexDirection::Column,
row_gap: px(4),
}
TabGroup::new(0)
Children [
{keys}
]
}
}
}
#[derive(EntityEvent, Reflect)]
#[reflect(Event)]
pub struct VirtualKeyPressed<T> {
pub entity: Entity,
pub key: T,
}