Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor remove multi #421

Merged
merged 1 commit into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
49 changes: 37 additions & 12 deletions core/src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,45 @@ 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 From<WidgetId> for Widget {
impl<T: Into<Widget>> WidgetBuilder for T {
#[inline]
fn from(id: WidgetId) -> Self { Widget(Box::new(move |_| id)) }
fn build(self, ctx: &BuildCtx) -> WidgetId { self.into().build(ctx) }
}

impl StrictBuilder for WidgetId {
fn strict_build(self, _: &BuildCtx) -> WidgetId { self }
}

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 +190,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 +323,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 +339,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