use bevy_ecs::prelude::*;
use bevy_picking::prelude::*;
use bevy_ui::prelude::*;
use jonmo::signal::{Signal, SignalExt};
use super::{
align::{Alignable, LayoutDirection},
element::{BuilderPassThrough, BuilderWrapper, IntoOptionElement, Nameable, UiRootable},
global_event_aware::GlobalEventAware,
mouse_wheel_scrollable::MouseWheelScrollable,
pointer_event_aware::{Cursorable, PointerEventAware},
viewport_mutable::ViewportMutable,
};
use crate::{clone_semantics_doc, impl_element_clone};
#[doc = clone_semantics_doc!("El")]
#[derive(Default)]
pub struct El<NodeType> {
builder: jonmo::Builder,
_node_type: std::marker::PhantomData<NodeType>,
}
impl_element_clone!("El", El<NodeType>, my_el, ".name(label)");
impl<NodeType: Bundle> From<jonmo::Builder> for El<NodeType> {
fn from(builder: jonmo::Builder) -> Self {
Self {
builder: builder
.with_component::<Node>(|mut node| {
node.display = Display::Flex;
node.flex_direction = FlexDirection::Column;
})
.insert((LayoutDirection::Column, Pickable::IGNORE)),
_node_type: std::marker::PhantomData,
}
}
}
impl<NodeType: Bundle + Default> El<NodeType> {
pub fn new() -> Self {
Self::from(jonmo::Builder::from(NodeType::default()))
}
}
impl<NodeType> BuilderWrapper for El<NodeType> {
fn builder_mut(&mut self) -> &mut jonmo::Builder {
&mut self.builder
}
}
impl<NodeType: Bundle> Alignable for El<NodeType> {}
impl<NodeType: Bundle> Cursorable for El<NodeType> {}
impl<NodeType: Bundle> GlobalEventAware for El<NodeType> {}
impl<NodeType: Bundle> Nameable for El<NodeType> {}
impl<NodeType: Bundle> PointerEventAware for El<NodeType> {}
impl<NodeType: Bundle> MouseWheelScrollable for El<NodeType> {}
impl<NodeType: Bundle> UiRootable for El<NodeType> {}
impl<NodeType: Bundle> ViewportMutable for El<NodeType> {}
impl<NodeType: Bundle> BuilderPassThrough for El<NodeType> {}
impl<NodeType: Bundle> El<NodeType> {
pub fn child<IOE: IntoOptionElement>(self, child_option: IOE) -> Self {
if let Some(child) = child_option.into_option_element() {
self.with_builder(|builder| builder.child(child.into_builder()))
} else {
self
}
}
pub fn child_signal<IOE, S>(self, child_option_signal_option: impl Into<Option<S>>) -> Self
where
IOE: IntoOptionElement + 'static,
S: Signal<Item = IOE> + Send + Sync + 'static,
{
if let Some(child_option_signal) = child_option_signal_option.into() {
self.with_builder(|builder| {
builder.child_signal(
child_option_signal.map_in(move |child_option: IOE| {
child_option.into_option_element().map(|el| el.into_builder())
}),
)
})
} else {
self
}
}
}