use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use bevy::ui::widget::Text;
use crate::components::{PfAutomationId, PfElementKind, PfName, PfUid, XamlNames};
#[derive(SystemParam)]
pub struct PfQuery<'w, 's> {
names: Query<'w, 's, (Entity, &'static PfName)>,
uids: Query<'w, 's, (Entity, &'static PfUid)>,
automation: Query<'w, 's, (Entity, &'static PfAutomationId)>,
kinds: Query<'w, 's, (Entity, &'static PfElementKind)>,
scopes: Query<'w, 's, &'static XamlNames>,
parents: Query<'w, 's, &'static ChildOf>,
children: Query<'w, 's, &'static Children>,
texts: Query<'w, 's, (), With<Text>>,
}
impl PfQuery<'_, '_> {
pub fn by_name(&self, name: &str) -> Option<Entity> {
self.names.iter().find(|(_, n)| n.0 == name).map(|(e, _)| e)
}
pub fn all_by_name(&self, name: &str) -> Vec<Entity> {
self.names
.iter()
.filter(|(_, n)| n.0 == name)
.map(|(e, _)| e)
.collect()
}
pub fn named_in(&self, root: Entity, name: &str) -> Option<Entity> {
self.scopes.get(root).ok().and_then(|s| s.get(name))
}
pub fn by_uid(&self, uid: &str) -> Option<Entity> {
self.uids.iter().find(|(_, u)| u.0 == uid).map(|(e, _)| e)
}
pub fn by_automation_id(&self, id: &str) -> Option<Entity> {
self.automation
.iter()
.find(|(_, a)| a.0 == id)
.map(|(e, _)| e)
}
pub fn by_kind(&self, kind: &str) -> Vec<Entity> {
self.kinds
.iter()
.filter(|(_, k)| k.0 == kind)
.map(|(e, _)| e)
.collect()
}
pub fn name_of(&self, entity: Entity) -> Option<&str> {
self.names.get(entity).ok().map(|(_, n)| n.0.as_str())
}
pub fn scope_root(&self, entity: Entity) -> Option<Entity> {
let mut current = entity;
loop {
if self.scopes.contains(current) {
return Some(current);
}
current = self.parents.get(current).ok()?.parent();
}
}
pub fn first_text_in(&self, element: Entity) -> Option<Entity> {
if self.texts.contains(element) {
return Some(element);
}
let children = self.children.get(element).ok()?;
for child in children.iter() {
if let Some(found) = self.first_text_in(child) {
return Some(found);
}
}
None
}
}