diff --git a/Cargo.toml b/Cargo.toml index 54392b4..0331224 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ crate-type = ["lib"] [features] default = [] test-api = [] +examples = ["macroquad-examples", "egui-examples"] macroquad-examples = ["macroquad"] egui-examples = ["egui", "eframe", "egui_extras"] diff --git a/README.md b/README.md index 72c491b..50fef1f 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,6 @@ The crate is currently usable but new! Breaking changes may be relatively freque > If your PR changes the public API, one of the checks will fail by default. > If the changes to the public API were intentional you can update the snapshot by running: > -> `INSTA_UPDATE=always && cargo test --features test-api` +> `INSTA_UPDATE=always cargo test --features test-api` Contributions are always welcome 🤗 diff --git a/examples/egui-example/src/main.rs b/examples/egui-example/src/main.rs index 19c680e..5e8b038 100644 --- a/examples/egui-example/src/main.rs +++ b/examples/egui-example/src/main.rs @@ -22,21 +22,23 @@ fn main() -> eframe::Result { } fn my_layout_fn<'n>() -> Node<'n, Ui> { - column_spaced( - 10., - vec![ - draw_a(ui), - row_spaced( - 10., - vec![ - draw_b(ui).width_range(200.0..), - column_spaced(10., vec![draw_a(ui), draw_b(ui), draw_c(ui)]), - ], - ), - draw_c(ui), - ], - ) - .pad(10.) + dynamic(|ui| { + column_spaced( + 10., + vec![ + draw_a(ui), + row_spaced( + 10., + vec![ + draw_b(ui).width_range(200.0..), + column_spaced(10., vec![draw_a(ui), draw_b(ui), draw_c(ui)]), + ], + ), + draw_c(ui), + ], + ) + .pad(10.) + }) } fn draw_a<'n>(ui: &mut Ui) -> Node<'n, Ui> { diff --git a/examples/macroquad-example/src/main.rs b/examples/macroquad-example/src/main.rs index c45f348..fc5a1a1 100644 --- a/examples/macroquad-example/src/main.rs +++ b/examples/macroquad-example/src/main.rs @@ -2,7 +2,6 @@ use backer::models::*; use backer::nodes::*; use backer::Layout; use backer::Node; -use backer::ScopeCtx; use macroquad::prelude::*; use macroquad::ui::root_ui; use macroquad::ui::widgets; @@ -50,9 +49,7 @@ fn layout_for_highlight<'n>() -> Node<'n, State> { || highlight == HighlightedCase::None { scope( - |ctx: ScopeCtx, state: &mut State| { - ctx.with_scoped(&mut state.highlight) - }, + |state: &mut State| &mut state.highlight, rel_abs_seq(highlight), ) } else { diff --git a/src/layout.rs b/src/layout.rs index b7098e5..b040951 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -278,8 +278,8 @@ impl NodeValue<'_, State> { NodeValue::Draw(_) | NodeValue::Space | NodeValue::AreaReader { .. } - | NodeValue::Coupled { .. } | NodeValue::NodeTrait { .. } + | NodeValue::Coupled { .. } | NodeValue::Dynamic { .. } => { vec![available_area] } @@ -346,7 +346,18 @@ impl NodeValue<'_, State> { element, coupled, .. } => { element.layout(allocated[0], None, None, state); - coupled.layout(allocated[0], None, None, state); + coupled.layout( + available_area.constrained( + &element + .constraints(available_area, state) + .unwrap_or_default(), + contextual_x_align.unwrap_or(XAlign::Center), + contextual_y_align.unwrap_or(YAlign::Center), + ), + None, + None, + state, + ); } NodeValue::Visibility { element, .. } => { element.layout(allocated[0], None, None, state); diff --git a/src/lib.rs b/src/lib.rs index 395960f..1957ade 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,6 @@ mod node; pub use node::Node; mod node_cache; mod scoper; -pub use scoper::{ScopeCtx, ScopeCtxResult}; mod subtree; mod tests; diff --git a/src/nodes.rs b/src/nodes.rs index 87b2a08..666ce74 100644 --- a/src/nodes.rs +++ b/src/nodes.rs @@ -3,7 +3,7 @@ use crate::{ layout::NodeValue, models::*, node_cache::NodeCache, - scoper::{ScopeCtx, ScopeCtxResult, Scoper}, + scoper::{OptionScoper, OwnedScoper, Scoper}, traits::Drawable, Node, }; @@ -25,10 +25,10 @@ or pushing against other unconstrained nodes with equal force. /// Creates a vertical sequence of elements /// #[doc = container_doc!()] -pub fn column(elements: Vec>) -> Node<'_, State> { +pub fn column<'n, State>(elements: Vec>>) -> Node<'n, State> { Node { inner: NodeValue::Column { - elements: filter_empty(ungroup(elements)), + elements: filter_empty(ungroup(convert_into(elements))), spacing: 0., align: None, off_axis_align: None, @@ -53,18 +53,21 @@ pub fn column(elements: Vec>) -> Node<'_, State> { /// ), /// ]); /// ``` -pub fn group(elements: Vec>) -> Node<'_, State> { +pub fn group<'n, State>(elements: Vec>>) -> Node<'n, State> { Node { - inner: NodeValue::Group(filter_empty(ungroup(elements))), + inner: NodeValue::Group(filter_empty(ungroup(convert_into(elements)))), } } /// Creates a vertical sequence of elements with the specified spacing between each element. /// #[doc = container_doc!()] -pub fn column_spaced(spacing: f32, elements: Vec>) -> Node<'_, State> { +pub fn column_spaced<'n, State>( + spacing: f32, + elements: Vec>>, +) -> Node<'n, State> { Node { inner: NodeValue::Column { - elements: filter_empty(ungroup(elements)), + elements: filter_empty(ungroup(convert_into(elements))), spacing, align: None, off_axis_align: None, @@ -74,10 +77,10 @@ pub fn column_spaced(spacing: f32, elements: Vec>) -> Node<'_ /// Creates a horizontal sequence of elements /// #[doc = container_doc!()] -pub fn row(elements: Vec>) -> Node<'_, State> { +pub fn row<'n, State>(elements: Vec>>) -> Node<'n, State> { Node { inner: NodeValue::Row { - elements: filter_empty(ungroup(elements)), + elements: filter_empty(ungroup(convert_into(elements))), spacing: 0., align: None, off_axis_align: None, @@ -87,10 +90,13 @@ pub fn row(elements: Vec>) -> Node<'_, State> { /// Creates a horizontal sequence of elements with the specified spacing between each element. /// #[doc = container_doc!()] -pub fn row_spaced(spacing: f32, elements: Vec>) -> Node<'_, State> { +pub fn row_spaced<'n, State>( + spacing: f32, + elements: Vec>>, +) -> Node<'n, State> { Node { inner: NodeValue::Row { - elements: filter_empty(ungroup(elements)), + elements: filter_empty(ungroup(convert_into(elements))), spacing, align: None, off_axis_align: None, @@ -100,10 +106,10 @@ pub fn row_spaced(spacing: f32, elements: Vec>) -> Node<'_, S /// Creates a sequence of elements to be laid out on top of each other. /// #[doc = container_doc!()] -pub fn stack(elements: Vec>) -> Node<'_, State> { +pub fn stack<'n, State>(elements: Vec>>) -> Node<'n, State> { Node { inner: NodeValue::Stack { - elements: filter_empty(ungroup(elements)), + elements: filter_empty(ungroup(convert_into(elements))), x_align: None, y_align: None, }, @@ -197,22 +203,13 @@ pub fn dynamic<'nodes, State>( /// use backer::nodes::*; /// /// struct A { -/// b: Option, +/// b: bool, /// } /// let layout = dynamic(|_: &mut A| { /// stack(vec![ /// scope( -/// // Explicit types are often necessary. -/// // bool is the type of the subset in this case -/// |ctx: ScopeCtx, a: &mut A| { -/// // This closure transforms state into the desired subset. -/// // The desired subset is passed to ctx.with_scoped(...) -/// // or the entire hierarchy can be skipped with ctx.empty() -/// let Some(ref mut b) = a.b else { -/// return ctx.empty(); -/// }; -/// ctx.with_scoped(b) -/// }, +/// // This closure selects which state to scope to +/// |a: &mut A| &mut a.b, /// // These nodes now have direct access to only the boolean /// draw(|_, b: &mut bool| *b = !*b), /// ), @@ -220,18 +217,57 @@ pub fn dynamic<'nodes, State>( /// }); ///``` pub fn scope<'nodes, State, Scoped: 'nodes>( - scope: impl Fn(ScopeCtx<'_, '_, Scoped>, &mut State) -> ScopeCtxResult + 'nodes, - node: Node<'nodes, Scoped>, + scope: impl Fn(&mut State) -> &mut Scoped + 'nodes, + node: impl Into>, ) -> Node<'nodes, State> { Node { inner: NodeValue::NodeTrait { node: Box::new(Scoper { - scope_fn: scope, - node, + scope, + node: node.into(), }), }, } } +/// Scopes state to some derived *optional* subset which is unwrapped for all children of this node +/// See `nodes::scope` +pub fn scope_unwrap<'nodes, State, Scoped: 'nodes>( + scope: impl Fn(&mut State) -> &mut Option + 'nodes, + node: impl Into>, +) -> Node<'nodes, State> { + Node { + inner: NodeValue::NodeTrait { + node: Box::new(OptionScoper { + scope, + node: node.into(), + }), + }, + } +} +/// Scopes state to some owned derivative for all children of this node +/// once the child nodes have operated on state, embed is then called. +/// +/// The scope & embed functions are generally called multiple times in a single `draw` call, use them sparingly +/// See `nodes::scope` +pub fn scope_owned<'nodes, State, Scoped: 'nodes>( + scope: impl Fn(&mut State) -> Scoped + 'nodes, + embed: impl Fn(&mut State, Scoped) + 'nodes, + node: impl Into>, +) -> Node<'nodes, State> { + Node { + inner: NodeValue::NodeTrait { + node: Box::new(OwnedScoper { + scope, + embed, + node: node.into(), + }), + }, + } +} + +fn convert_into<'n, State>(elements: Vec>>) -> Vec> { + elements.into_iter().map(|e| e.into()).collect() +} fn ungroup(elements: Vec>) -> Vec> { elements diff --git a/src/scoper.rs b/src/scoper.rs index 1f16d99..b3c52c8 100644 --- a/src/scoper.rs +++ b/src/scoper.rs @@ -1,109 +1,132 @@ -use std::fmt::Debug; - use crate::{ constraints::SizeConstraints, models::{Area, XAlign, YAlign}, traits::NodeTrait, Node, }; +use std::fmt::Debug; -pub(crate) struct Scoper<'n, SubState, ScopeStateFn> { - pub(crate) scope_fn: ScopeStateFn, - pub(crate) node: Node<'n, SubState>, +pub(crate) struct Scoper<'nodes, ScopedState, Scope> { + pub(crate) scope: Scope, + pub(crate) node: Node<'nodes, ScopedState>, +} + +impl Debug for Scoper<'_, ScopedState, Scope> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Scoper") + .field("scope", &"") + .field("node", &self.node) + .finish() + } } -/// Anonymous result to return from the closure passed to `nodes::scope` -/// See `nodes::scope` -pub struct ScopeCtxResult { - value: ResultValue, +impl NodeTrait for Scoper<'_, ScopedState, Scope> +where + Scope: Fn(&mut State) -> &mut ScopedState, +{ + fn constraints(&mut self, available_area: Area, state: &mut State) -> Option { + let substate = (self.scope)(state); + self.node.inner.constraints(available_area, substate) + } + + fn layout( + &mut self, + available_area: Area, + contextual_x_align: Option, + contextual_y_align: Option, + state: &mut State, + ) { + let substate = (self.scope)(state); + self.node.inner.layout( + available_area, + contextual_x_align, + contextual_y_align, + substate, + ); + } + + fn draw(&mut self, state: &mut State, contextual_visibility: bool) { + let substate = (self.scope)(state); + self.node.inner.draw(substate, contextual_visibility); + } } -enum ResultValue { - Void, - Constraints(Option), +pub(crate) struct OptionScoper<'nodes, ScopedState, Scope> { + pub(crate) scope: Scope, + pub(crate) node: Node<'nodes, ScopedState>, } -impl Debug for Scoper<'_, SubState, ScopeStateFn> { +impl Debug for OptionScoper<'_, ScopedState, Scope> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Scoper") - .field("scope_fn", &"") + f.debug_struct("OptionScoper") + .field("scope", &"") .field("node", &self.node) .finish() } } -type WithScopedFnPointer = fn( - area: Area, - contextual_x_align: Option, - contextual_y_align: Option, - contextual_visibility: bool, - &mut Node, - &mut SubState, -) -> ResultValue; - -/// Contextual state for scoping, see `nodes::scope` -pub struct ScopeCtx<'a, 'nodes, SubState> { - node: &'a mut Node<'nodes, SubState>, - area: Area, - contextual_x_align: Option, - contextual_y_align: Option, - contextual_visibility: bool, - with_scoped: WithScopedFnPointer, -} +impl NodeTrait for OptionScoper<'_, ScopedState, Scope> +where + Scope: Fn(&mut State) -> &mut Option, +{ + fn constraints(&mut self, available_area: Area, state: &mut State) -> Option { + if let Some(substate) = (self.scope)(state) { + self.node.inner.constraints(available_area, substate) + } else { + None + } + } -impl ScopeCtx<'_, '_, SubState> { - /// Takes the subset of state being scoped to, returns an anonymous result to be returned from the closure passed into `nodes::scope` - pub fn with_scoped(self, scoped: &mut SubState) -> ScopeCtxResult { - ScopeCtxResult { - value: (self.with_scoped)( - self.area, - self.contextual_x_align, - self.contextual_y_align, - self.contextual_visibility, - self.node, - scoped, - ), + fn layout( + &mut self, + available_area: Area, + contextual_x_align: Option, + contextual_y_align: Option, + state: &mut State, + ) { + if let Some(substate) = (self.scope)(state) { + self.node.inner.layout( + available_area, + contextual_x_align, + contextual_y_align, + substate, + ) } } - /// Used when scoping to a state that is potentially "invalid", such as when scoping to an `Option` in a way that will unwrap the state for the child nodes - /// Returns an anonymous result to be returned from the closure passed into `nodes::scope` - pub fn empty(self) -> ScopeCtxResult { - ScopeCtxResult { - value: ResultValue::Void, + + fn draw(&mut self, state: &mut State, contextual_visibility: bool) { + if let Some(substate) = (self.scope)(state) { + self.node.inner.draw(substate, contextual_visibility) } } } -impl<'nodes, State, SubState, ScopeStateFn> NodeTrait - for Scoper<'nodes, SubState, ScopeStateFn> +pub(crate) struct OwnedScoper<'nodes, ScopedState, Scope, Embed> { + pub(crate) scope: Scope, + pub(crate) embed: Embed, + pub(crate) node: Node<'nodes, ScopedState>, +} + +impl Debug for OwnedScoper<'_, ScopedState, Scope, Embed> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("OwnedScoper") + .field("scope", &"") + .field("node", &self.node) + .finish() + } +} + +impl NodeTrait + for OwnedScoper<'_, ScopedState, Scope, Embed> where - ScopeStateFn: Fn(ScopeCtx<'_, 'nodes, SubState>, &mut State) -> ScopeCtxResult, + Scope: Fn(&mut State) -> ScopedState, + Embed: Fn(&mut State, ScopedState), { fn constraints(&mut self, available_area: Area, state: &mut State) -> Option { - let ScopeCtxResult { - value: ResultValue::Constraints(constraints), - } = (self.scope_fn)( - ScopeCtx { - node: &mut self.node, - area: available_area, - contextual_x_align: None, - contextual_y_align: None, - contextual_visibility: false, - with_scoped: |area: Area, - _contextual_x_align: Option, - _contextual_y_align: Option, - _contextual_visibility: bool, - node: &mut Node, - sc: &mut SubState| { - ResultValue::Constraints(node.inner.constraints(area, sc)) - }, - }, - state, - ) - else { - return None; - }; - constraints + let mut substate = (self.scope)(state); + let result = self.node.inner.constraints(available_area, &mut substate); + (self.embed)(state, substate); + result } fn layout( @@ -113,57 +136,19 @@ where contextual_y_align: Option, state: &mut State, ) { - let ScopeCtxResult { - value: ResultValue::Void, - } = (self.scope_fn)( - ScopeCtx { - node: &mut self.node, - area: available_area, - contextual_x_align, - contextual_y_align, - contextual_visibility: false, - with_scoped: |available_area: Area, - contextual_x_align: Option, - contextual_y_align: Option, - _contextual_visibility: bool, - node: &mut Node, - sc: &mut SubState| { - node.inner - .layout(available_area, contextual_x_align, contextual_y_align, sc); - ResultValue::Void - }, - }, - state, - ) - else { - return; - }; + let mut substate = (self.scope)(state); + self.node.inner.layout( + available_area, + contextual_x_align, + contextual_y_align, + &mut substate, + ); + (self.embed)(state, substate); } fn draw(&mut self, state: &mut State, contextual_visibility: bool) { - let ScopeCtxResult { - value: ResultValue::Void, - } = (self.scope_fn)( - ScopeCtx { - node: &mut self.node, - area: Area::zero(), - contextual_x_align: None, - contextual_y_align: None, - contextual_visibility, - with_scoped: |_available_area: Area, - _contextual_x_align: Option, - _contextual_y_align: Option, - contextual_visibility: bool, - node: &mut Node, - sc: &mut SubState| { - node.inner.draw(sc, contextual_visibility); - ResultValue::Void - }, - }, - state, - ) - else { - return; - }; + let mut substate = (self.scope)(state); + self.node.inner.draw(&mut substate, contextual_visibility); + (self.embed)(state, substate); } } diff --git a/src/tests/layout_tests.rs b/src/tests/layout_tests.rs index a26e322..ef0f122 100644 --- a/src/tests/layout_tests.rs +++ b/src/tests/layout_tests.rs @@ -615,9 +615,12 @@ mod tests { .width_range(20.0..) .pad(0.) .attach_under(draw(|a, _: &mut ()| { - assert_eq!(a, Area::new(45., 0., 10., 100.)); + assert_eq!(a, Area::new(40., 0., 20., 100.)); })) .width_range(..10.) + .attach_under(draw(|a, _: &mut ()| { + assert_eq!(a, Area::new(45., 0., 10., 100.)); + })) }) .draw(Area::new(0., 0., 100., 100.), &mut ()); } @@ -669,4 +672,22 @@ mod tests { }) .draw(Area::new(0., 0., 100., 100.), &mut ()); } + #[test] + fn test_dynamic_attached() { + Layout::new({ + row(vec![ + space(), + draw(|a, _: &mut ()| { + assert_eq!(a, Area::new(25., 25., 25., 50.)); + }) + .dynamic_height(|h, _| h * 2.) + .attach_under(draw(|a, _: &mut ()| { + assert_eq!(a, Area::new(25., 25., 25., 50.)); + })), + space(), + space(), + ]) + }) + .draw(Area::new(0., 0., 100., 100.), &mut ()); + } } diff --git a/src/tests/scope_tests.rs b/src/tests/scope_tests.rs index 4d428ef..6c137af 100644 --- a/src/tests/scope_tests.rs +++ b/src/tests/scope_tests.rs @@ -1,10 +1,8 @@ #[cfg(test)] mod tests { - use crate::layout::*; use crate::models::*; use crate::nodes::*; - use crate::scoper::ScopeCtx; #[test] fn test_scope() { @@ -37,7 +35,7 @@ mod tests { } }, scope( - |ctx: ScopeCtx, a: &mut A| ctx.with_scoped(&mut a.b), + |a: &mut A| &mut a.b, dynamic(|b: &mut B| { if b.test { draw(|area, b: &mut B| { @@ -73,19 +71,13 @@ mod tests { } Layout::new(stack(vec![ scope( - |ctx: ScopeCtx, a: &mut A| { - //> - ctx.with_scoped(&mut a.b) - }, + |a: &mut A| &mut a.b, draw(|area, _state: &mut B| { assert_eq!(area, Area::new(0., 0., 100., 100.)); }), ), scope( - |ctx: ScopeCtx, a: &mut A| { - //> - ctx.with_scoped(&mut a.c) - }, + |a: &mut A| &mut a.c, draw(|area, _state: &mut C| { assert_eq!(area, Area::new(0., 0., 100., 100.)); }), @@ -105,16 +97,7 @@ mod tests { let layout = dynamic(|_: &mut A| { stack(vec![ //> - scope( - |ctx: ScopeCtx, a: &mut A| { - //> - let Some(ref mut b) = a.b else { - return ctx.empty(); - }; - ctx.with_scoped(b) - }, - draw(|_, b: &mut B| b.test = !b.test), - ), + scope_unwrap(|a: &mut A| &mut a.b, draw(|_, b: &mut B| b.test = !b.test)), ]) }); let mut state = A { @@ -141,10 +124,10 @@ mod tests { // let mut oneone = A { b: B }; // Layout::new(stack(vec![ // //> - // scope( - // |ctx: ScopeCtx, a: &mut One| { + // scope_owned( + // |a: &mut One| { // //> - // ctx.with_scoped(&mut (&mut a.0.b, a.1)) + // (&mut a.0.b, a.1.borrow_mut()) // }, // space(), // ), diff --git a/src/tests/snapshots/backer__tests__public_api_test__api_full.snap b/src/tests/snapshots/backer__tests__public_api_test__api_full.snap index 72c1658..0db1135 100644 --- a/src/tests/snapshots/backer__tests__public_api_test__api_full.snap +++ b/src/tests/snapshots/backer__tests__public_api_test__api_full.snap @@ -100,20 +100,22 @@ impl core::convert::From for backer::models::Area pub fn backer::models::Area::from(t: T) -> T pub mod backer::nodes pub fn backer::nodes::area_reader<'nodes, State>(func: impl core::ops::function::Fn(backer::models::Area, &mut State) -> backer::Node<'nodes, State> + 'static) -> backer::Node<'nodes, State> -pub fn backer::nodes::column(elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::column_spaced(spacing: f32, elements: alloc::vec::Vec>) -> backer::Node<'_, State> +pub fn backer::nodes::column<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::column_spaced<'n, State>(spacing: f32, elements: alloc::vec::Vec>>) -> backer::Node<'n, State> pub fn backer::nodes::draw<'nodes, State>(drawable_fn: impl core::ops::function::Fn(backer::models::Area, &mut State) + 'static) -> backer::Node<'nodes, State> -pub fn backer::nodes::draw_object<'nodes, State>(drawable: impl backer::traits::Drawable<'nodes, State> + 'nodes) -> backer::Node<'nodes, State> -pub fn backer::nodes::dynamic<'nodes, State: 'nodes>(func: impl core::ops::function::Fn(&mut State) -> backer::Node<'nodes, State> + 'nodes) -> backer::Node<'nodes, State> +pub fn backer::nodes::draw_object<'nodes, State>(drawable: impl backer::traits::Drawable + 'nodes) -> backer::Node<'nodes, State> +pub fn backer::nodes::dynamic<'nodes, State>(func: impl core::ops::function::Fn(&mut State) -> backer::Node<'nodes, State> + 'nodes) -> backer::Node<'nodes, State> pub fn backer::nodes::empty<'nodes, State>() -> backer::Node<'nodes, State> -pub fn backer::nodes::group(elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::row(elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::row_spaced(spacing: f32, elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::scope<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(backer::ScopeCtx<'_, '_, Scoped>, &mut State) -> backer::ScopeCtxResult + 'nodes, node: backer::Node<'nodes, Scoped>) -> backer::Node<'nodes, State> +pub fn backer::nodes::group<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::row<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::row_spaced<'n, State>(spacing: f32, elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::scope<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(&mut State) -> &mut Scoped + 'nodes, node: impl core::convert::Into>) -> backer::Node<'nodes, State> +pub fn backer::nodes::scope_owned<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(&mut State) -> Scoped + 'nodes, embed: impl core::ops::function::Fn(&mut State, Scoped) + 'nodes, node: impl core::convert::Into>) -> backer::Node<'nodes, State> +pub fn backer::nodes::scope_unwrap<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(&mut State) -> &mut core::option::Option + 'nodes, node: impl core::convert::Into>) -> backer::Node<'nodes, State> pub fn backer::nodes::space<'nodes, State>() -> backer::Node<'nodes, State> -pub fn backer::nodes::stack(elements: alloc::vec::Vec>) -> backer::Node<'_, State> +pub fn backer::nodes::stack<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> pub mod backer::traits -pub trait backer::traits::Drawable<'nodes, State> +pub trait backer::traits::Drawable pub fn backer::traits::Drawable::draw(&mut self, area: backer::models::Area, state: &mut State, visible: bool) pub struct backer::Layout<'nodes, State> impl<'nodes, State> backer::Layout<'nodes, State> @@ -194,52 +196,3 @@ impl core::borrow::BorrowMut for backer::Node<'nodes, State> where T: ?cor pub fn backer::Node<'nodes, State>::borrow_mut(&mut self) -> &mut T impl core::convert::From for backer::Node<'nodes, State> pub fn backer::Node<'nodes, State>::from(t: T) -> T -pub struct backer::ScopeCtx<'a, 'nodes, SubState> -impl backer::ScopeCtx<'_, '_, SubState> -pub fn backer::ScopeCtx<'_, '_, SubState>::empty(self) -> backer::ScopeCtxResult -pub fn backer::ScopeCtx<'_, '_, SubState>::with_scoped(self, scoped: &mut SubState) -> backer::ScopeCtxResult -impl<'a, 'nodes, SubState> core::marker::Freeze for backer::ScopeCtx<'a, 'nodes, SubState> -impl<'a, 'nodes, SubState> !core::marker::Send for backer::ScopeCtx<'a, 'nodes, SubState> -impl<'a, 'nodes, SubState> !core::marker::Sync for backer::ScopeCtx<'a, 'nodes, SubState> -impl<'a, 'nodes, SubState> core::marker::Unpin for backer::ScopeCtx<'a, 'nodes, SubState> -impl<'a, 'nodes, SubState> !core::panic::unwind_safe::RefUnwindSafe for backer::ScopeCtx<'a, 'nodes, SubState> -impl<'a, 'nodes, SubState> !core::panic::unwind_safe::UnwindSafe for backer::ScopeCtx<'a, 'nodes, SubState> -impl core::convert::Into for backer::ScopeCtx<'a, 'nodes, SubState> where U: core::convert::From -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::into(self) -> U -impl core::convert::TryFrom for backer::ScopeCtx<'a, 'nodes, SubState> where U: core::convert::Into -pub type backer::ScopeCtx<'a, 'nodes, SubState>::Error = core::convert::Infallible -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for backer::ScopeCtx<'a, 'nodes, SubState> where U: core::convert::TryFrom -pub type backer::ScopeCtx<'a, 'nodes, SubState>::Error = >::Error -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for backer::ScopeCtx<'a, 'nodes, SubState> where T: 'static + ?core::marker::Sized -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for backer::ScopeCtx<'a, 'nodes, SubState> where T: ?core::marker::Sized -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::borrow(&self) -> &T -impl core::borrow::BorrowMut for backer::ScopeCtx<'a, 'nodes, SubState> where T: ?core::marker::Sized -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::borrow_mut(&mut self) -> &mut T -impl core::convert::From for backer::ScopeCtx<'a, 'nodes, SubState> -pub fn backer::ScopeCtx<'a, 'nodes, SubState>::from(t: T) -> T -pub struct backer::ScopeCtxResult -impl core::marker::Freeze for backer::ScopeCtxResult -impl core::marker::Send for backer::ScopeCtxResult -impl core::marker::Sync for backer::ScopeCtxResult -impl core::marker::Unpin for backer::ScopeCtxResult -impl core::panic::unwind_safe::RefUnwindSafe for backer::ScopeCtxResult -impl core::panic::unwind_safe::UnwindSafe for backer::ScopeCtxResult -impl core::convert::Into for backer::ScopeCtxResult where U: core::convert::From -pub fn backer::ScopeCtxResult::into(self) -> U -impl core::convert::TryFrom for backer::ScopeCtxResult where U: core::convert::Into -pub type backer::ScopeCtxResult::Error = core::convert::Infallible -pub fn backer::ScopeCtxResult::try_from(value: U) -> core::result::Result>::Error> -impl core::convert::TryInto for backer::ScopeCtxResult where U: core::convert::TryFrom -pub type backer::ScopeCtxResult::Error = >::Error -pub fn backer::ScopeCtxResult::try_into(self) -> core::result::Result>::Error> -impl core::any::Any for backer::ScopeCtxResult where T: 'static + ?core::marker::Sized -pub fn backer::ScopeCtxResult::type_id(&self) -> core::any::TypeId -impl core::borrow::Borrow for backer::ScopeCtxResult where T: ?core::marker::Sized -pub fn backer::ScopeCtxResult::borrow(&self) -> &T -impl core::borrow::BorrowMut for backer::ScopeCtxResult where T: ?core::marker::Sized -pub fn backer::ScopeCtxResult::borrow_mut(&mut self) -> &mut T -impl core::convert::From for backer::ScopeCtxResult -pub fn backer::ScopeCtxResult::from(t: T) -> T diff --git a/src/tests/snapshots/backer__tests__public_api_test__api_simplified.snap b/src/tests/snapshots/backer__tests__public_api_test__api_simplified.snap index 23eb8a3..420cefa 100644 --- a/src/tests/snapshots/backer__tests__public_api_test__api_simplified.snap +++ b/src/tests/snapshots/backer__tests__public_api_test__api_simplified.snap @@ -29,19 +29,23 @@ impl backer::models::Area pub fn backer::models::Area::new(x: f32, y: f32, width: f32, height: f32) -> Self pub mod backer::nodes pub fn backer::nodes::area_reader<'nodes, State>(func: impl core::ops::function::Fn(backer::models::Area, &mut State) -> backer::Node<'nodes, State> + 'static) -> backer::Node<'nodes, State> -pub fn backer::nodes::column(elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::column_spaced(spacing: f32, elements: alloc::vec::Vec>) -> backer::Node<'_, State> +pub fn backer::nodes::column<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::column_spaced<'n, State>(spacing: f32, elements: alloc::vec::Vec>>) -> backer::Node<'n, State> pub fn backer::nodes::draw<'nodes, State>(drawable_fn: impl core::ops::function::Fn(backer::models::Area, &mut State) + 'static) -> backer::Node<'nodes, State> -pub fn backer::nodes::draw_object<'nodes, State>(drawable: impl backer::traits::drawable::Drawable<'nodes, State> + 'nodes) -> backer::Node<'nodes, State> -pub fn backer::nodes::dynamic<'nodes, State: 'nodes>(func: impl core::ops::function::Fn(&mut State) -> backer::Node<'nodes, State> + 'nodes) -> backer::Node<'nodes, State> +pub fn backer::nodes::draw_object<'nodes, State>(drawable: impl backer::traits::Drawable + 'nodes) -> backer::Node<'nodes, State> +pub fn backer::nodes::dynamic<'nodes, State>(func: impl core::ops::function::Fn(&mut State) -> backer::Node<'nodes, State> + 'nodes) -> backer::Node<'nodes, State> pub fn backer::nodes::empty<'nodes, State>() -> backer::Node<'nodes, State> -pub fn backer::nodes::group(elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::row(elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::row_spaced(spacing: f32, elements: alloc::vec::Vec>) -> backer::Node<'_, State> -pub fn backer::nodes::scope<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(backer::ScopeCtx<'_, '_, Scoped>, &mut State) -> backer::ScopeCtxResult + 'nodes, node: backer::Node<'nodes, Scoped>) -> backer::Node<'nodes, State> +pub fn backer::nodes::group<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::row<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::row_spaced<'n, State>(spacing: f32, elements: alloc::vec::Vec>>) -> backer::Node<'n, State> +pub fn backer::nodes::scope<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(&mut State) -> &mut Scoped + 'nodes, node: impl core::convert::Into>) -> backer::Node<'nodes, State> +pub fn backer::nodes::scope_owned<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(&mut State) -> Scoped + 'nodes, embed: impl core::ops::function::Fn(&mut State, Scoped) + 'nodes, node: impl core::convert::Into>) -> backer::Node<'nodes, State> +pub fn backer::nodes::scope_unwrap<'nodes, State, Scoped: 'nodes>(scope: impl core::ops::function::Fn(&mut State) -> &mut core::option::Option + 'nodes, node: impl core::convert::Into>) -> backer::Node<'nodes, State> pub fn backer::nodes::space<'nodes, State>() -> backer::Node<'nodes, State> -pub fn backer::nodes::stack(elements: alloc::vec::Vec>) -> backer::Node<'_, State> +pub fn backer::nodes::stack<'n, State>(elements: alloc::vec::Vec>>) -> backer::Node<'n, State> pub mod backer::traits +pub trait backer::traits::Drawable +pub fn backer::traits::Drawable::draw(&mut self, area: backer::models::Area, state: &mut State, visible: bool) pub struct backer::Layout<'nodes, State> impl<'nodes, State> backer::Layout<'nodes, State> pub fn backer::Layout<'nodes, State>::new(tree: backer::Node<'nodes, State>) -> Self @@ -77,8 +81,3 @@ pub fn backer::Node<'_, State>::dynamic_height(self, f: impl core::ops::function pub fn backer::Node<'_, State>::dynamic_width(self, f: impl core::ops::function::Fn(f32, &mut State) -> f32 + 'static) -> Self impl core::fmt::Debug for backer::Node<'_, State> pub fn backer::Node<'_, State>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result -pub struct backer::ScopeCtx<'a, 'nodes, SubState> -impl backer::ScopeCtx<'_, '_, SubState> -pub fn backer::ScopeCtx<'_, '_, SubState>::empty(self) -> backer::ScopeCtxResult -pub fn backer::ScopeCtx<'_, '_, SubState>::with_scoped(self, scoped: &mut SubState) -> backer::ScopeCtxResult -pub struct backer::ScopeCtxResult