Skip to content

Commit

Permalink
refactor(ribir): 💡 remove ctx! macro and fn widget no longer requir…
Browse files Browse the repository at this point in the history
…es a `BuildCtx` parameter
  • Loading branch information
M-Adoo committed Nov 7, 2024
1 parent 6b1155f commit d469c1c
Show file tree
Hide file tree
Showing 55 changed files with 423 additions and 475 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he

<!-- next-header -->

## [@Unreleased] - @ReleaseDat
## [@Unreleased] - @ReleaseDate

### Features

- **core**: Added the smooth widgets for transitioning the layout position and size. (#645 @M-Adoo)
- **widgets**: Added three widgets `FractionallyWidthBox`, `FractionallyHeightBox`, and `FractionallySizedBox` to enable fractional sizing of widgets. (#647 @M-Adoo)
- **widgets**: Add widget of radio button (#649 @wjian23)
- **core**: `BuildCtx::get()` and `BuildCtx::get_mut()` have been added to facilitate access from anywhere within a build context. (#pr @M-Adoo)
- **core**: `BuildCtx::get()` and `BuildCtx::get_mut()` have been added to facilitate access from anywhere within a build context. (#650 @M-Adoo)

### Fixed

Expand All @@ -40,7 +40,9 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he
### Breaking

- **core**: `Expanded` and `KeyWidget` are not declared with `FatObj`, so they do not currently support built-in widgets. (#648 @M-Adoo)
- **core**: `DeclareObj::finish` does not accept a `BuildCtx` parameter. (#pr @M-Adoo)
- **core**: `DeclareObj::finish` does not accept a `BuildCtx` parameter. (#650 @M-Adoo)
- **core**: function widget no longer requires a `&mut BuildCtx` parameter. (#650 @M-Adoo)
- **macros**: Removed the `ctx!` macro. (#650 @M-Adoo)

## [0.4.0-alpha.14] - 2024-10-30

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn main() {
use ribir::prelude::*;

fn main() {
let counter = |_: &mut BuildCtx| {
let counter = || {
let cnt = Stateful::new(0);

let c_cnt = cnt.clone_writer();
Expand Down
31 changes: 13 additions & 18 deletions core/src/animation/stagger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,22 @@
//! use ribir::prelude::*;
//!
//! let _ = fn_widget! {
//! let ctx = BuildCtx::get();
//! let mut stagger = Stagger::new(
//! Duration::from_millis(100),
//! transitions::EASE_IN.of(ctx!())
//! transitions::EASE_IN.of(ctx)
//! );
//!
//! let mut first = @Text { text: "first" };
//! let mut second = @Text { text: "second" };
//! let first_opacity = first
//! .get_opacity_widget()
//! .map_writer(|w| PartData::from_ref_mut(&mut w.opacity));
//! let second_opacity = second
//! .get_opacity_widget()
//! .map_writer(|w| PartData::from_ref_mut(&mut w.opacity));
//!
//!
//! let first_fade_in = @Animate {
//! transition: transitions::EASE_IN.of(ctx!()),
//! state: first_opacity,
//! transition: transitions::EASE_IN.of(ctx),
//! state: part_writer!(&mut first.opacity),
//! };
//!
//! stagger.write().push_animation(first_fade_in);
//! stagger.write().push_state(second_opacity, 0., ctx!());
//! stagger.write().push_state(part_writer!(&mut second.opacity), 0.);
//!
//! @Column {
//! on_mounted: move |_| stagger.run(),
Expand Down Expand Up @@ -81,11 +75,11 @@ impl<T: Transition + 'static> Stagger<T> {
///
/// **state**: the state you want to transition.
/// **from**: the state you want to transition from.
pub fn push_state<A>(&mut self, state: A, from: A::Value, ctx: &BuildCtx) -> State<Animate<A>>
pub fn push_state<A>(&mut self, state: A, from: A::Value) -> State<Animate<A>>
where
A: AnimateState + 'static,
{
self.push_state_with(self.default_stagger(), state, from, ctx)
self.push_state_with(self.default_stagger(), state, from)
}

/// Add an new state as animation to the end of the stagger animation with a
Expand All @@ -96,7 +90,7 @@ impl<T: Transition + 'static> Stagger<T> {
/// - **state**: the state you want to transition.
/// - **from**: the state you want to transition from.
pub fn push_state_with<A>(
&mut self, stagger: Duration, state: A, from: A::Value, ctx!(): &BuildCtx,
&mut self, stagger: Duration, state: A, from: A::Value,
) -> State<Animate<A>>
where
A: AnimateState + 'static,
Expand Down Expand Up @@ -228,11 +222,14 @@ mod tests {
widget_layout_test!(
stagger_run_and_stop,
WidgetTester::new(fn_widget! {
let stagger = Stagger::new(Duration::from_millis(100), transitions::EASE_IN.of(ctx!()));
let stagger = Stagger::new(
Duration::from_millis(100),
transitions::EASE_IN.of(BuildCtx::get())
);
let mut mock_box = @MockBox { size: Size::new(100., 100.) };

let animate = @Animate {
transition: transitions::EASE_IN.of(ctx!()),
transition: transitions::EASE_IN.of(BuildCtx::get()),
state: part_writer!(&mut mock_box.opacity),
from: 0.,
};
Expand All @@ -241,7 +238,6 @@ mod tests {
stagger.write().push_state(
part_writer!(&mut mock_box.size),
Size::new(200., 200.),
ctx!()
);


Expand Down Expand Up @@ -271,7 +267,6 @@ mod tests {
.get_opacity_widget()
.map_writer(|w| PartData::from_ref_mut(&mut w.opacity)),
0.,
ctx!()
);
stagger.run();

Expand Down
2 changes: 1 addition & 1 deletion core/src/builtin_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl LazyWidgetId {
/// Bind a widget to the LazyWidgetId, and return a widget that will set the
/// id to the LazyWidgetId after build.
pub fn bind(self, widget: Widget) -> Widget {
widget.on_build(move |id, _| {
widget.on_build(move |id| {
assert!(self.id().is_none(), "The LazyWidgetID only allows binding to one widget.");
self.0.set(Some(id));
})
Expand Down
23 changes: 12 additions & 11 deletions core/src/builtin_widgets/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,19 @@ impl<'c> ComposeChild<'c> for Class {
type Child = Widget<'c>;

fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'c> {
let f = move |ctx: &mut BuildCtx| match this.try_into_value() {
let f = move || match this.try_into_value() {
Ok(c) => c.apply_style(child),
Err(this) => {
let this2 = this.clone_watcher();
let cls_child = ClassChild::new(ctx.tree().dummy_id());
let cls_child = ClassChild::new(BuildCtx::get().tree().dummy_id());
// Reapply the class when it is updated.
let cls_child2 = cls_child.clone();
let child = child.on_build(move |orig_id, ctx| {
let mut orig_child = OrigChild::from_id(orig_id, ctx);
let child = child.on_build(move |orig_id| {
let tree = BuildCtx::get_mut().tree_mut();
let mut orig_child = OrigChild::from_id(orig_id, tree);
cls_child2.inner().orig_id = orig_id;
let orig_child2 = orig_child.clone();
let wnd_id = ctx.window().id();
let wnd_id = tree.window().id();
let u = this2
.raw_modifies()
.filter(|s| s.contains(ModifyScope::FRAMEWORK))
Expand All @@ -147,7 +148,7 @@ impl<'c> ComposeChild<'c> for Class {
this
.read()
.apply_style(child)
.on_build(move |child_id, ctx| cls_child.set_child_id(child_id, ctx))
.on_build(move |child_id| cls_child.set_child_id(child_id))
}
};
f.into_widget()
Expand Down Expand Up @@ -195,10 +196,10 @@ impl ClassChild {
Self(Sc::new(UnsafeCell::new(inner)))
}

fn set_child_id(&self, id: WidgetId, ctx: &mut BuildCtx) {
fn set_child_id(&self, id: WidgetId) {
let inner = self.inner();
inner.child_id = id;
id.wrap_node(ctx.tree_mut(), |node| {
id.wrap_node(BuildCtx::get_mut().tree_mut(), |node| {
inner.child = node;
Box::new(self.clone())
});
Expand All @@ -208,7 +209,7 @@ impl ClassChild {
let wnd =
AppCtx::get_window(wnd_id).expect("This handle is not valid because the window is closed");
let InnerClassChild { child, child_id, orig_id } = self.inner();
let _guard = BuildCtx::set_ctx_for(*child_id, wnd.tree);
let _guard = BuildCtx::init_for(*child_id, wnd.tree);
let n_orig = BuildCtx::get_mut().alloc(Box::new(orig.clone()));
let tree = BuildCtx::get_mut().tree_mut();
let cls_holder = child_id.place_holder(tree);
Expand Down Expand Up @@ -278,9 +279,9 @@ impl ClassChild {
}

impl OrigChild {
fn from_id(id: WidgetId, ctx: &mut BuildCtx) -> Self {
fn from_id(id: WidgetId, tree: &mut WidgetTree) -> Self {
let mut orig = None;
id.wrap_node(ctx.tree_mut(), |node| {
id.wrap_node(tree, |node| {
let c = OrigChild(Sc::new(UnsafeCell::new(node)));
orig = Some(c.clone());
Box::new(c)
Expand Down
34 changes: 13 additions & 21 deletions core/src/builtin_widgets/global_anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl<'c> ComposeChild<'c> for GlobalAnchor {
type Child = Widget<'c>;
fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'c> {
fn_widget! {
let wnd = ctx!().window();
let wnd = BuildCtx::get().window();
let tick_of_layout_ready = wnd
.frame_tick_stream()
.filter(|msg| matches!(msg, FrameMsg::LayoutReady(_)));
Expand Down Expand Up @@ -87,11 +87,9 @@ impl<W> FatObj<W> {
/// the left edge of the specified widget (`wid`) with the given relative
/// pixel value (`relative`).
// Todo: Should we control the subscription in the inner part?
pub fn left_align_to(
&mut self, wid: &LazyWidgetId, offset: f32, ctx: &BuildCtx,
) -> impl Subscription {
pub fn left_align_to(&mut self, wid: &LazyWidgetId, offset: f32) -> impl Subscription {
let this = self.get_global_anchor_widget().clone_writer();
let wnd = ctx.window();
let wnd = BuildCtx::get().window();
let wid = wid.clone();
let tick_of_layout_ready = wnd
.frame_tick_stream()
Expand All @@ -107,11 +105,9 @@ impl<W> FatObj<W> {
/// Anchor the widget's horizontal position by placing its right edge left to
/// the right edge of the specified widget (`wid`) with the given relative
/// pixel value (`relative`).
pub fn right_align_to(
&mut self, wid: &LazyWidgetId, relative: f32, ctx: &BuildCtx,
) -> impl Subscription {
pub fn right_align_to(&mut self, wid: &LazyWidgetId, relative: f32) -> impl Subscription {
let this = self.get_global_anchor_widget().clone_writer();
let wnd = ctx.window();
let wnd = BuildCtx::get().window();
let wid = wid.clone();
let tick_of_layout_ready = wnd
.frame_tick_stream()
Expand All @@ -130,11 +126,9 @@ impl<W> FatObj<W> {
/// Anchors the widget's vertical position by placing its top edge below the
/// top edge of the specified widget (`wid`) with the given relative pixel
/// value (`relative`).
pub fn top_align_to(
&mut self, wid: &LazyWidgetId, relative: f32, ctx: &BuildCtx,
) -> impl Subscription {
pub fn top_align_to(&mut self, wid: &LazyWidgetId, relative: f32) -> impl Subscription {
let this = self.get_global_anchor_widget().clone_writer();
let wnd = ctx.window();
let wnd = BuildCtx::get().window();
let wid = wid.clone();
let tick_of_layout_ready = wnd
.frame_tick_stream()
Expand All @@ -150,11 +144,9 @@ impl<W> FatObj<W> {
/// Anchors the widget's vertical position by placing its bottom edge above
/// the bottom edge of the specified widget (`wid`) with the given relative
/// pixel value (`relative`).
pub fn bottom_align_to(
&mut self, wid: &LazyWidgetId, relative: f32, ctx: &BuildCtx,
) -> impl Subscription {
pub fn bottom_align_to(&mut self, wid: &LazyWidgetId, relative: f32) -> impl Subscription {
let this = self.get_global_anchor_widget().clone_writer();
let wnd = ctx.window();
let wnd = BuildCtx::get().window();
let wid = wid.clone();
let tick_of_layout_ready = wnd
.frame_tick_stream()
Expand Down Expand Up @@ -190,14 +182,14 @@ mod tests {
let mut top_left = @MockBox {
size: Size::new(10., 10.),
};
top_left.left_align_to(&wid, 20., ctx!());
top_left.top_align_to(&wid, 10., ctx!());
top_left.left_align_to(&wid, 20.);
top_left.top_align_to(&wid, 10.);

let mut bottom_right = @MockBox {
size: Size::new(10., 10.),
};
bottom_right.right_align_to(&wid, 10., ctx!());
bottom_right.bottom_align_to(&wid, 20., ctx!());
bottom_right.right_align_to(&wid, 10.);
bottom_right.bottom_align_to(&wid, 20.);
@ $parent {
@MockStack {
@ { top_left }
Expand Down
2 changes: 1 addition & 1 deletion core/src/builtin_widgets/keep_alive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl<'c> ComposeChild<'c> for KeepAlive {
let modifies = this.raw_modifies();
child
.try_unwrap_state_and_attach(this)
.on_build(|id, ctx| id.dirty_subscribe(modifies, ctx))
.on_build(|id| id.dirty_subscribe(modifies, BuildCtx::get_mut().tree_mut()))
}
}

Expand Down
37 changes: 16 additions & 21 deletions core/src/builtin_widgets/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ use crate::{prelude::*, window::WindowId};
/// Provider::new(Box::new(Queryable(1i32)))
/// // Provider only accepts function widgets as its child.
/// .with_child(fn_widget! {
/// let value = Provider::of::<i32>(ctx!()).unwrap();
/// let value = Provider::of::<i32>(BuildCtx::get()).unwrap();
/// assert_eq!(*value, 1);
///
/// let value = Provider::write_of::<i32>(ctx!());
/// let value = Provider::write_of::<i32>(BuildCtx::get());
/// // We not share a writer.
/// assert!(value.is_none());
/// @Text { text: "Good!" }
Expand All @@ -49,20 +49,21 @@ use crate::{prelude::*, window::WindowId};
///
/// Provider::new(Box::new(Stateful::new(0i32))).with_child(fn_widget! {
/// // we can query the type of the data.
/// let ctx = BuildCtx::get();
/// {
/// let cnt = Provider::of::<Stateful<i32>>(ctx!()).unwrap();
/// let cnt = Provider::of::<Stateful<i32>>(ctx).unwrap();
/// assert_eq!(*cnt.read(), 0);
/// }
///
/// // the write ref of the value
/// {
/// let mut cnt: WriteRef<i32> = Provider::write_of::<i32>(ctx!()).unwrap();
/// let mut cnt: WriteRef<i32> = Provider::write_of::<i32>(ctx).unwrap();
/// assert_eq!(*cnt, 0);
/// *cnt = 1;
/// }
///
/// // The value type of the state.
/// let cnt = Provider::of::<i32>(ctx!()).unwrap();
/// let cnt = Provider::of::<i32>(ctx).unwrap();
/// assert_eq!(*cnt, 1);
/// @Text { text: "Good!" }
/// });
Expand All @@ -78,7 +79,7 @@ pub struct Provider {
/// use ribir::prelude::*;
///
/// providers![State::value(0), Queryable("Hello!")].with_child(fn_widget! {
/// let hi = Provider::of::<&'static str>(ctx!()).unwrap();
/// let hi = Provider::of::<&'static str>(BuildCtx::get()).unwrap();
/// @Text { text: *hi }
/// });
/// ```
Expand Down Expand Up @@ -125,20 +126,14 @@ impl<'c> ComposeChild<'c> for Provider {
})
.provider;

let f = move |_: &mut BuildCtx| {
let ctx = BuildCtx::get_mut();

// We need to consume the root widget keep its build logic can access the
// provider.
// Allow the building logic to access the provider.
ctx.current_providers.push(provider);
let (child, child_id) = child.into_widget().consume_root();
// We push the provider into the build context to ensure that the widget build
// logic can access this provider.
let ctx = BuildCtx::get_mut();
ctx.current_providers.push(provider);
child.into_widget().on_build(|id| {
let provider = ctx.current_providers.pop().unwrap();
child_id.attach_data(provider, ctx.tree_mut());

child
};
f.into_widget()
id.attach_data(provider, ctx.tree_mut());
})
}
}

Expand Down Expand Up @@ -284,7 +279,7 @@ mod tests {
let w = fn_widget! {
let w_value = w_value.clone_writer();
Provider::new(Box::new(Queryable(1i32))).with_child(fn_widget! {
let v = Provider::of::<i32>(ctx!()).unwrap();
let v = Provider::of::<i32>(BuildCtx::get()).unwrap();
*w_value.write() = *v;
Void
})
Expand All @@ -306,7 +301,7 @@ mod tests {
@MockBox {
size: Size::new(1.,1.),
@ {
let v = Provider::of::<i32>(ctx!()).unwrap();
let v = Provider::of::<i32>(BuildCtx::get()).unwrap();
*$w_value.write() = *v;
Void
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/builtin_widgets/smooth_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ macro_rules! smooth_size_widget_impl {
fn_widget!{
let modifies = this.read().0.raw_modifies();
WrapRender::combine_child(this, child)
.on_build(move |id, ctx| id.dirty_subscribe(modifies, ctx))
.on_build(move |id, | id.dirty_subscribe(modifies, BuildCtx::get_mut().tree_mut()) )
}.into_widget()
}
}
Expand Down
Loading

0 comments on commit d469c1c

Please sign in to comment.