use blinc_core::{Brush, Color, Shadow, Transform};
use taffy::{LengthPercentageAuto, Overflow, Position, Rect, Style};
use crate::div::Div;
use crate::element::{Material, RenderLayer, RenderProps};
use crate::tree::{LayoutNodeId, LayoutTree};
use crate::ElementBuilder;
pub struct Stack {
inner: Div,
}
impl Stack {
pub fn new() -> Self {
let mut inner = Div::new();
inner.style.position = Position::Relative;
inner.style.overflow.x = Overflow::Clip;
inner.style.overflow.y = Overflow::Clip;
Self { inner }
}
pub fn child(mut self, child: impl ElementBuilder + 'static) -> Self {
let wrapper = StackChild::new(Box::new(child));
self.inner.children.push(Box::new(wrapper));
self
}
pub fn children<I>(mut self, children: I) -> Self
where
I: IntoIterator,
I::Item: ElementBuilder + 'static,
{
for child in children {
let wrapper = StackChild::new(Box::new(child));
self.inner.children.push(Box::new(wrapper));
}
self
}
}
impl Default for Stack {
fn default() -> Self {
Self::new()
}
}
impl Stack {
pub fn flex(mut self) -> Self {
self.inner = self.inner.flex();
self
}
pub fn block(mut self) -> Self {
self.inner = self.inner.block();
self
}
pub fn grid(mut self) -> Self {
self.inner = self.inner.grid();
self
}
pub fn hidden(mut self) -> Self {
self.inner = self.inner.hidden();
self
}
pub fn flex_row(mut self) -> Self {
self.inner = self.inner.flex_row();
self
}
pub fn flex_col(mut self) -> Self {
self.inner = self.inner.flex_col();
self
}
pub fn flex_row_reverse(mut self) -> Self {
self.inner = self.inner.flex_row_reverse();
self
}
pub fn flex_col_reverse(mut self) -> Self {
self.inner = self.inner.flex_col_reverse();
self
}
pub fn flex_grow(mut self) -> Self {
self.inner = self.inner.flex_grow();
self
}
pub fn flex_shrink(mut self) -> Self {
self.inner = self.inner.flex_shrink();
self
}
pub fn flex_auto(mut self) -> Self {
self.inner = self.inner.flex_auto();
self
}
pub fn flex_wrap(mut self) -> Self {
self.inner = self.inner.flex_wrap();
self
}
pub fn items_center(mut self) -> Self {
self.inner = self.inner.items_center();
self
}
pub fn items_start(mut self) -> Self {
self.inner = self.inner.items_start();
self
}
pub fn items_end(mut self) -> Self {
self.inner = self.inner.items_end();
self
}
pub fn items_stretch(mut self) -> Self {
self.inner = self.inner.items_stretch();
self
}
pub fn items_baseline(mut self) -> Self {
self.inner = self.inner.items_baseline();
self
}
pub fn justify_start(mut self) -> Self {
self.inner = self.inner.justify_start();
self
}
pub fn justify_center(mut self) -> Self {
self.inner = self.inner.justify_center();
self
}
pub fn justify_end(mut self) -> Self {
self.inner = self.inner.justify_end();
self
}
pub fn justify_between(mut self) -> Self {
self.inner = self.inner.justify_between();
self
}
pub fn justify_around(mut self) -> Self {
self.inner = self.inner.justify_around();
self
}
pub fn justify_evenly(mut self) -> Self {
self.inner = self.inner.justify_evenly();
self
}
pub fn w(mut self, px: f32) -> Self {
self.inner = self.inner.w(px);
self
}
pub fn w_full(mut self) -> Self {
self.inner = self.inner.w_full();
self
}
pub fn w_auto(mut self) -> Self {
self.inner = self.inner.w_auto();
self
}
pub fn w_fit(mut self) -> Self {
self.inner = self.inner.w_fit();
self
}
pub fn h(mut self, px: f32) -> Self {
self.inner = self.inner.h(px);
self
}
pub fn h_full(mut self) -> Self {
self.inner = self.inner.h_full();
self
}
pub fn h_auto(mut self) -> Self {
self.inner = self.inner.h_auto();
self
}
pub fn h_fit(mut self) -> Self {
self.inner = self.inner.h_fit();
self
}
pub fn size_fit(mut self) -> Self {
self.inner = self.inner.size_fit();
self
}
pub fn size(mut self, w: f32, h: f32) -> Self {
self.inner = self.inner.size(w, h);
self
}
pub fn square(mut self, size: f32) -> Self {
self.inner = self.inner.square(size);
self
}
pub fn min_w(mut self, px: f32) -> Self {
self.inner = self.inner.min_w(px);
self
}
pub fn min_h(mut self, px: f32) -> Self {
self.inner = self.inner.min_h(px);
self
}
pub fn max_w(mut self, px: f32) -> Self {
self.inner = self.inner.max_w(px);
self
}
pub fn max_h(mut self, px: f32) -> Self {
self.inner = self.inner.max_h(px);
self
}
pub fn gap(mut self, units: f32) -> Self {
self.inner = self.inner.gap(units);
self
}
pub fn gap_px(mut self, px: f32) -> Self {
self.inner = self.inner.gap_px(px);
self
}
pub fn gap_x(mut self, units: f32) -> Self {
self.inner = self.inner.gap_x(units);
self
}
pub fn gap_y(mut self, units: f32) -> Self {
self.inner = self.inner.gap_y(units);
self
}
pub fn p(mut self, units: f32) -> Self {
self.inner = self.inner.p(units);
self
}
pub fn p_px(mut self, px: f32) -> Self {
self.inner = self.inner.p_px(px);
self
}
pub fn px(mut self, units: f32) -> Self {
self.inner = self.inner.px(units);
self
}
pub fn py(mut self, units: f32) -> Self {
self.inner = self.inner.py(units);
self
}
pub fn pl(mut self, units: f32) -> Self {
self.inner = self.inner.pl(units);
self
}
pub fn pr(mut self, units: f32) -> Self {
self.inner = self.inner.pr(units);
self
}
pub fn pt(mut self, units: f32) -> Self {
self.inner = self.inner.pt(units);
self
}
pub fn pb(mut self, units: f32) -> Self {
self.inner = self.inner.pb(units);
self
}
pub fn padding_x_px(mut self, pixels: f32) -> Self {
self.inner = self.inner.padding_x_px(pixels);
self
}
pub fn padding_y_px(mut self, pixels: f32) -> Self {
self.inner = self.inner.padding_y_px(pixels);
self
}
pub fn m(mut self, units: f32) -> Self {
self.inner = self.inner.m(units);
self
}
pub fn m_px(mut self, px: f32) -> Self {
self.inner = self.inner.m_px(px);
self
}
pub fn mx(mut self, units: f32) -> Self {
self.inner = self.inner.mx(units);
self
}
pub fn my(mut self, units: f32) -> Self {
self.inner = self.inner.my(units);
self
}
pub fn mx_auto(mut self) -> Self {
self.inner = self.inner.mx_auto();
self
}
pub fn ml(mut self, units: f32) -> Self {
self.inner = self.inner.ml(units);
self
}
pub fn mr(mut self, units: f32) -> Self {
self.inner = self.inner.mr(units);
self
}
pub fn mt(mut self, units: f32) -> Self {
self.inner = self.inner.mt(units);
self
}
pub fn mb(mut self, units: f32) -> Self {
self.inner = self.inner.mb(units);
self
}
pub fn absolute(mut self) -> Self {
self.inner = self.inner.absolute();
self
}
pub fn inset(mut self, px: f32) -> Self {
self.inner = self.inner.inset(px);
self
}
pub fn top(mut self, px: f32) -> Self {
self.inner = self.inner.top(px);
self
}
pub fn bottom(mut self, px: f32) -> Self {
self.inner = self.inner.bottom(px);
self
}
pub fn left(mut self, px: f32) -> Self {
self.inner = self.inner.left(px);
self
}
pub fn right(mut self, px: f32) -> Self {
self.inner = self.inner.right(px);
self
}
pub fn overflow_clip(mut self) -> Self {
self.inner = self.inner.overflow_clip();
self
}
pub fn overflow_visible(mut self) -> Self {
self.inner = self.inner.overflow_visible();
self
}
pub fn overflow_scroll(mut self) -> Self {
self.inner = self.inner.overflow_scroll();
self
}
pub fn overflow_x(mut self, overflow: Overflow) -> Self {
self.inner = self.inner.overflow_x(overflow);
self
}
pub fn overflow_y(mut self, overflow: Overflow) -> Self {
self.inner = self.inner.overflow_y(overflow);
self
}
pub fn bg(mut self, color: Color) -> Self {
self.inner = self.inner.bg(color);
self
}
pub fn background(mut self, brush: impl Into<Brush>) -> Self {
self.inner = self.inner.background(brush);
self
}
pub fn rounded(mut self, radius: f32) -> Self {
self.inner = self.inner.rounded(radius);
self
}
pub fn rounded_full(mut self) -> Self {
self.inner = self.inner.rounded_full();
self
}
pub fn rounded_corners(mut self, tl: f32, tr: f32, br: f32, bl: f32) -> Self {
self.inner = self.inner.rounded_corners(tl, tr, br, bl);
self
}
pub fn border(mut self, width: f32, color: Color) -> Self {
self.inner = self.inner.border(width, color);
self
}
pub fn border_color(mut self, color: Color) -> Self {
self.inner = self.inner.border_color(color);
self
}
pub fn border_width(mut self, width: f32) -> Self {
self.inner = self.inner.border_width(width);
self
}
pub fn layer(mut self, layer: RenderLayer) -> Self {
self.inner = self.inner.layer(layer);
self
}
pub fn foreground(self) -> Self {
Self {
inner: self.inner.foreground(),
}
}
pub fn material(mut self, material: Material) -> Self {
self.inner = self.inner.material(material);
self
}
pub fn effect(self, effect: impl Into<Material>) -> Self {
Self {
inner: self.inner.effect(effect),
}
}
pub fn glass(self) -> Self {
Self {
inner: self.inner.glass(),
}
}
pub fn metallic(self) -> Self {
Self {
inner: self.inner.metallic(),
}
}
pub fn chrome(self) -> Self {
Self {
inner: self.inner.chrome(),
}
}
pub fn gold(self) -> Self {
Self {
inner: self.inner.gold(),
}
}
pub fn wood(self) -> Self {
Self {
inner: self.inner.wood(),
}
}
pub fn shadow(mut self, shadow: Shadow) -> Self {
self.inner = self.inner.shadow(shadow);
self
}
pub fn shadow_params(self, offset_x: f32, offset_y: f32, blur: f32, color: Color) -> Self {
Self {
inner: self.inner.shadow_params(offset_x, offset_y, blur, color),
}
}
pub fn shadow_sm(self) -> Self {
Self {
inner: self.inner.shadow_sm(),
}
}
pub fn shadow_md(self) -> Self {
Self {
inner: self.inner.shadow_md(),
}
}
pub fn shadow_lg(self) -> Self {
Self {
inner: self.inner.shadow_lg(),
}
}
pub fn shadow_xl(self) -> Self {
Self {
inner: self.inner.shadow_xl(),
}
}
pub fn transform(mut self, transform: Transform) -> Self {
self.inner = self.inner.transform(transform);
self
}
pub fn translate(self, x: f32, y: f32) -> Self {
Self {
inner: self.inner.translate(x, y),
}
}
pub fn scale(self, factor: f32) -> Self {
Self {
inner: self.inner.scale(factor),
}
}
pub fn scale_xy(self, sx: f32, sy: f32) -> Self {
Self {
inner: self.inner.scale_xy(sx, sy),
}
}
pub fn rotate(self, angle: f32) -> Self {
Self {
inner: self.inner.rotate(angle),
}
}
pub fn rotate_deg(self, degrees: f32) -> Self {
Self {
inner: self.inner.rotate_deg(degrees),
}
}
pub fn opacity(mut self, opacity: f32) -> Self {
self.inner = self.inner.opacity(opacity);
self
}
pub fn opaque(self) -> Self {
Self {
inner: self.inner.opaque(),
}
}
pub fn translucent(self) -> Self {
Self {
inner: self.inner.translucent(),
}
}
pub fn invisible(self) -> Self {
Self {
inner: self.inner.invisible(),
}
}
pub fn on_click<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_click(handler);
self
}
pub fn on_mouse_down<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_mouse_down(handler);
self
}
pub fn on_mouse_up<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_mouse_up(handler);
self
}
pub fn on_mouse_move<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_mouse_move(handler);
self
}
pub fn on_drag<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_drag(handler);
self
}
pub fn on_scroll<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_scroll(handler);
self
}
pub fn on_hover_enter<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_hover_enter(handler);
self
}
pub fn on_hover_leave<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_hover_leave(handler);
self
}
pub fn on_focus<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_focus(handler);
self
}
pub fn on_blur<F>(mut self, handler: F) -> Self
where
F: Fn(&crate::event_handler::EventContext) + Send + Sync + 'static,
{
self.inner = self.inner.on_blur(handler);
self
}
pub fn cursor(mut self, cursor: crate::element::CursorStyle) -> Self {
self.inner = self.inner.cursor(cursor);
self
}
pub fn cursor_pointer(self) -> Self {
self.cursor(crate::element::CursorStyle::Pointer)
}
pub fn cursor_text(self) -> Self {
self.cursor(crate::element::CursorStyle::Text)
}
pub fn cursor_move(self) -> Self {
self.cursor(crate::element::CursorStyle::Move)
}
pub fn cursor_grab(self) -> Self {
self.cursor(crate::element::CursorStyle::Grab)
}
pub fn cursor_grabbing(self) -> Self {
self.cursor(crate::element::CursorStyle::Grabbing)
}
pub fn cursor_not_allowed(self) -> Self {
self.cursor(crate::element::CursorStyle::NotAllowed)
}
#[inline]
pub fn when<F>(self, condition: bool, f: F) -> Self
where
F: FnOnce(Self) -> Self,
{
if condition {
f(self)
} else {
self
}
}
}
impl ElementBuilder for Stack {
fn build(&self, tree: &mut LayoutTree) -> LayoutNodeId {
self.inner.build(tree)
}
fn render_props(&self) -> RenderProps {
self.inner.render_props()
}
fn children_builders(&self) -> &[Box<dyn ElementBuilder>] {
self.inner.children_builders()
}
fn event_handlers(&self) -> Option<&crate::event_handler::EventHandlers> {
if self.inner.event_handlers.is_empty() {
None
} else {
Some(&self.inner.event_handlers)
}
}
fn layout_style(&self) -> Option<&taffy::Style> {
self.inner.layout_style()
}
}
struct StackChild {
children: Vec<Box<dyn ElementBuilder>>,
style: Style,
}
impl StackChild {
fn new(child: Box<dyn ElementBuilder>) -> Self {
let style = Style {
position: Position::Absolute,
inset: Rect {
left: LengthPercentageAuto::Length(0.0),
right: LengthPercentageAuto::Length(0.0),
top: LengthPercentageAuto::Length(0.0),
bottom: LengthPercentageAuto::Length(0.0),
},
overflow: taffy::Point {
x: Overflow::Clip,
y: Overflow::Clip,
},
..Style::default()
};
Self {
children: vec![child],
style,
}
}
}
impl ElementBuilder for StackChild {
fn build(&self, tree: &mut LayoutTree) -> LayoutNodeId {
let wrapper = tree.create_node(self.style.clone());
if let Some(child) = self.children.first() {
let child_node = child.build(tree);
tree.add_child(wrapper, child_node);
}
wrapper
}
fn render_props(&self) -> RenderProps {
RenderProps {
clips_content: true,
is_stack_layer: true,
pointer_events_none: true,
..RenderProps::default()
}
}
fn children_builders(&self) -> &[Box<dyn ElementBuilder>] {
&self.children
}
fn layout_style(&self) -> Option<&taffy::Style> {
Some(&self.style)
}
}
pub fn stack() -> Stack {
Stack::new()
}