Skip to content

Commit

Permalink
refactor(core): 💡 remove Multi and support type implement `IntoIter…
Browse files Browse the repository at this point in the history
…ator` as multi child
  • Loading branch information
M-Adoo committed Sep 14, 2023
1 parent 726a824 commit 2d04245
Show file tree
Hide file tree
Showing 20 changed files with 168 additions and 177 deletions.
6 changes: 3 additions & 3 deletions core/src/builtin_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub use focus_node::*;
pub mod focus_scope;
pub use focus_scope::*;

use crate::{prelude::*, widget::WidgetBuilder};
use crate::{prelude::*, widget::StrictBuilder};

macro_rules! impl_builtin_obj {
($($builtin_ty: ty),*) => {
Expand Down Expand Up @@ -185,8 +185,8 @@ impl<T> FatObj<T> {
}
}

impl<T: Into<Widget>> WidgetBuilder for FatObj<T> {
fn build(self, ctx: &BuildCtx) -> WidgetId {
impl<T: Into<Widget>> StrictBuilder for FatObj<T> {
fn strict_build(self, ctx: &BuildCtx) -> WidgetId {
let Self { host, builtin } = self;
builtin.compose_with_host(host.into(), ctx).build(ctx)
}
Expand Down
5 changes: 2 additions & 3 deletions core/src/builtin_widgets/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,11 @@ mod tests {
@MockMulti {
@ {
pipe!(*$cnt).map(move |cnt| {
let iter = (0..cnt).map(move |_| @MockBox {
(0..cnt).map(move |_| @MockBox {
size: Size::zero(),
on_mounted: move |e| { $mounted.write().insert(e.id); },
on_disposed: move |e| { $disposed.write().insert(e.id); },
});
Multi::new(iter)
})
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/builtin_widgets/theme.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Theme use to share visual config or style compose logic. It can be defined
//! to app-wide or particular part of the application.
use crate::{fill_svgs, impl_query_self_only, prelude::*, widget::WidgetBuilder};
use crate::{fill_svgs, impl_query_self_only, prelude::*, widget::StrictBuilder};
pub use ribir_algo::{CowArc, ShareResource};
use ribir_geom::Size;
use ribir_macros::Declare2;
Expand Down Expand Up @@ -82,7 +82,7 @@ impl ComposeChild for ThemeWidget {

AppCtx::load_font_from_theme(&theme);
ctx.push_theme(theme.clone());
let p = DataWidget::new(Box::new(Void), theme).build(ctx);
let p = DataWidget::new(Box::new(Void), theme).strict_build(ctx);
let old = ctx.force_as_mut().reset_ctx_from(Some(p));
let c = child.build(ctx);
ctx.append_child(p, c);
Expand Down
41 changes: 17 additions & 24 deletions core/src/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
impl_proxy_render,
prelude::*,
ticker::FrameMsg,
widget::{Query, QueryOrder, Render, Widget, WidgetBuilder, WidgetId, WidgetTree},
widget::{Query, QueryOrder, Render, StrictBuilder, Widget, WidgetBuilder, WidgetId, WidgetTree},
window::WindowId,
};

Expand Down Expand Up @@ -84,8 +84,8 @@ impl<V> Pipe<V> {
pub fn value_mut(&mut self) -> &mut V { &mut self.value }
}

impl<W: Into<Widget> + 'static> WidgetBuilder for Pipe<W> {
fn build(self, ctx: &BuildCtx) -> WidgetId {
impl<W: Into<Widget> + 'static> StrictBuilder for Pipe<W> {
fn strict_build(self, ctx: &BuildCtx) -> WidgetId {
let (v, modifies) = self.unzip();
let id = v.into().build(ctx);
let id_share = Sc::new(Cell::new(id));
Expand Down Expand Up @@ -166,7 +166,7 @@ impl<W: Into<Widget> + 'static> WidgetBuilder for Pipe<Option<W>> {
fn build(self, ctx: &crate::context::BuildCtx) -> WidgetId {
self
.map(|w| w.map_or_else(|| Widget::from(Void), |w| w.into()))
.build(ctx)
.strict_build(ctx)
}
}

Expand All @@ -183,11 +183,11 @@ impl<W: SingleParent + 'static> SingleParent for Pipe<W> {
}
}

impl<W: MultiParent + 'static> MultiParent for Pipe<W> {
impl<W: MultiParent + StrictBuilder + 'static> MultiParent for Pipe<W> {
fn append_children(self, children: Vec<WidgetId>, ctx: &mut BuildCtx) -> WidgetId {
// if children is empty, we can let the pipe parent as the whole subtree.
if children.is_empty() {
self.build(ctx)
self.strict_build(ctx)
} else {
let (v, modifies) = self.unzip();
let first_child = children[0];
Expand All @@ -202,7 +202,7 @@ impl<W: MultiParent + 'static> MultiParent for Pipe<W> {
}
}

impl<W: SingleParent + 'static> SingleParent for Pipe<Option<W>> {
impl<W: SingleParent + Into<Widget> + 'static> SingleParent for Pipe<Option<W>> {
fn append_child(self, child: WidgetId, ctx: &mut BuildCtx) -> WidgetId {
self
.map(|p| -> Box<dyn BoxedSingleParent> {
Expand Down Expand Up @@ -275,24 +275,20 @@ fn update_pipe_parent<W: 'static>(
attach_unsubscribe_guard(parent.start, ctx.window().id(), unsub);
}

impl<W: 'static> Pipe<Multi<W>> {
impl<W: 'static> Pipe<W> {
pub(crate) fn build_multi(self, vec: &mut Vec<WidgetId>, ctx: &mut BuildCtx)
where
W: IntoIterator,
W::Item: Into<Widget>,
W::Item: WidgetBuilder,
{
fn build_multi(
v: Multi<impl IntoIterator<Item = impl Into<Widget>>>,
v: impl IntoIterator<Item = impl WidgetBuilder>,
ctx: &mut BuildCtx,
) -> Vec<WidgetId> {
let mut ids = v
.into_inner()
.into_iter()
.map(|w| w.into().build(ctx))
.collect::<Vec<_>>();
let mut ids = v.into_iter().map(|w| w.build(ctx)).collect::<Vec<_>>();

if ids.is_empty() {
ids.push(Void.build(ctx));
ids.push(Void.strict_build(ctx));
}

ids
Expand Down Expand Up @@ -643,14 +639,13 @@ mod tests {
@MockMulti {
@ {
pipe!($v.clone()).map(move |v| {
let iter = v.into_iter().map(move |_| {
v.into_iter().map(move |_| {
@MockBox{
size: Size::zero(),
on_mounted: move |_| *$new_cnt.write() += 1,
on_disposed: move |_| *$drop_cnt.write() += 1
}
});
Multi::new(iter)
})
})
}
}
Expand Down Expand Up @@ -733,7 +728,7 @@ mod tests {
@MockMulti {
@ {
pipe!($v.clone()).map(move |v| {
let iter = v.into_iter().map(move |(i, c)| {
v.into_iter().map(move |(i, c)| {
let mut key = @KeyWidget { key: i, value: c };
@$key {
@MockBox {
Expand All @@ -753,8 +748,7 @@ mod tests {
}
}
}
});
Multi::new(iter)
})
})
}
}
Expand Down Expand Up @@ -909,8 +903,7 @@ mod tests {
let w = fn_widget! {
@MockMulti {
@ { pipe!{
let iter = $c_tasks.iter().map(|t| build(t.clone_writer())).collect::<Vec<_>>();
Multi::new(iter)
$c_tasks.iter().map(|t| build(t.clone_writer())).collect::<Vec<_>>()
}}
}
};
Expand Down
6 changes: 3 additions & 3 deletions core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use stateful::*;
use crate::{
context::BuildCtx,
prelude::{MultiChild, SingleChild},
widget::{Compose, Render, WidgetBuilder, WidgetId},
widget::{Compose, Render, StrictBuilder, WidgetId},
};

/// The `StateReader` trait allows for reading, clone and map the state.
Expand Down Expand Up @@ -190,9 +190,9 @@ impl<W: Render + 'static> From<State<W>> for Box<dyn Render> {
}
}

impl<C: Compose> WidgetBuilder for State<C> {
impl<C: Compose> StrictBuilder for State<C> {
#[inline]
fn build(self, ctx: &BuildCtx) -> WidgetId { Compose::compose(self).build(ctx) }
fn strict_build(self, ctx: &BuildCtx) -> WidgetId { Compose::compose(self).build(ctx) }
}

impl<W> State<W> {
Expand Down
46 changes: 36 additions & 10 deletions core/src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,36 @@ impl<'a> dyn Render + 'a {

pub struct FnWidget<F>(F);

/// Trait to build a type to a widget, `StrictBuilder` and `WidgetBuilder` is
/// only for type distinction and help us to build complex widget.
///
///
/// These type implement this trait:
///
/// - type implemented `Compose` trait
/// - type implemented `Render` trait
/// - `ComposePair<_,_>`
/// - `SinglePair<_, _>`
/// - `MultiPair<_, _>`
/// - `Pipe<W>` if `W` implement `LooseBuilder`
pub(crate) trait StrictBuilder {
fn strict_build(self, ctx: &BuildCtx) -> WidgetId;
}

/// Trait to build a type to a widget and allow to create new widget in build
/// phase.
///
/// - Types implemented `StrictBuilder` will auto implement `WidgetBuilder`
/// - `Pipe<Option<W>>` directly implement this trait.
pub(crate) trait WidgetBuilder {
fn build(self, ctx: &BuildCtx) -> WidgetId;
}

impl<T: Into<Widget>> WidgetBuilder for T {
#[inline]
fn build(self, ctx: &BuildCtx) -> WidgetId { self.into().build(ctx) }
}

impl From<WidgetId> for Widget {
#[inline]
fn from(id: WidgetId) -> Self { Widget(Box::new(move |_| id)) }
Expand All @@ -156,7 +182,7 @@ impl<F> FnWidget<F> {
#[inline]
pub fn new<R>(f: F) -> Self
where
F: FnOnce(&BuildCtx) -> R + Into<FnWidget<F>>,
F: FnOnce(&BuildCtx) -> R,
{
FnWidget(f)
}
Expand All @@ -165,12 +191,12 @@ impl<F> FnWidget<F> {
pub fn into_inner(self) -> F { self.0 }
}

impl<F, R> WidgetBuilder for FnWidget<F>
impl<F, R> StrictBuilder for FnWidget<F>
where
F: FnOnce(&BuildCtx) -> R + 'static,
R: Into<Widget>,
R: WidgetBuilder,
{
fn build(self, ctx: &BuildCtx) -> WidgetId { (self.0)(ctx).into().build(ctx) }
fn strict_build(self, ctx: &BuildCtx) -> WidgetId { (self.0)(ctx).build(ctx) }
}

#[macro_export]
Expand Down Expand Up @@ -298,14 +324,14 @@ macro_rules! impl_proxy_render {
};
}

impl<C: Compose> WidgetBuilder for C {
impl<C: Compose> StrictBuilder for C {
#[inline]
fn build(self, ctx: &BuildCtx) -> WidgetId { State::value(self).build(ctx) }
fn strict_build(self, ctx: &BuildCtx) -> WidgetId { State::value(self).strict_build(ctx) }
}

impl<C: Compose> WidgetBuilder for Stateful<C> {
impl<C: Compose> StrictBuilder for Stateful<C> {
#[inline]
fn build(self, ctx: &BuildCtx) -> WidgetId { State::stateful(self).build(ctx) }
fn strict_build(self, ctx: &BuildCtx) -> WidgetId { State::stateful(self).strict_build(ctx) }
}

impl<R: Render + 'static> Compose for R {
Expand All @@ -314,9 +340,9 @@ impl<R: Render + 'static> Compose for R {
}
}

impl<W: WidgetBuilder + 'static> From<W> for Widget {
impl<W: StrictBuilder + 'static> From<W> for Widget {
#[inline]
fn from(value: W) -> Self { Self(Box::new(|ctx| value.build(ctx))) }
fn from(value: W) -> Self { Self(Box::new(|ctx| value.strict_build(ctx))) }
}

impl<F, R> From<F> for FnWidget<F>
Expand Down
Loading

0 comments on commit 2d04245

Please sign in to comment.