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

fix(core): 🐛 changing flex does not relayout #652

Merged
merged 1 commit into from
Nov 8, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he

- **core**: The `Provider` might be missing in a pipe class. (#648 @M-Adoo)
- **core**: The child generated by the class may not be mounted. (#648 @M-Adoo)
- **widgets**: Changing the `flex` of `Expanded` does not trigger a relayout. (#652 @M-Adoo)

### Breaking

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| id.dirty_subscribe(modifies, BuildCtx::get_mut().tree_mut()))
.on_build(|id| id.dirty_on(modifies))
}
}

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, | id.dirty_subscribe(modifies, BuildCtx::get_mut().tree_mut()) )
.on_build(move |id, | id.dirty_on(modifies) )
}.into_widget()
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ where
Err(s) => {
let modifies = s.raw_modifies();
let w = ReaderRender(s.clone_reader()).into_widget();
w.on_build(move |id| id.dirty_subscribe(modifies, BuildCtx::get_mut().tree_mut()))
w.on_build(move |id| id.dirty_on(modifies))
}
},
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ impl<'w> Widget<'w> {
self.on_build(|id| id.attach_anonymous_data(data, BuildCtx::get_mut().tree_mut()))
}

pub(crate) fn attach_data(self, data: Box<dyn Query>) -> Self {
pub fn attach_data(self, data: Box<dyn Query>) -> Self {
self.on_build(|id| id.attach_data(data, BuildCtx::get_mut().tree_mut()))
}

Expand Down
13 changes: 8 additions & 5 deletions core/src/widget_tree/widget_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ impl WidgetId {
tree.arena.get(self.0).map(|n| &**n.get())
}

/// Subscribe the modifies `upstream` to mark the widget dirty when the
/// `upstream` emit a modify event that contains `ModifyScope::FRAMEWORK`.
pub(crate) fn dirty_subscribe(
self, upstream: CloneableBoxOp<'static, ModifyScope, Infallible>, tree: &mut WidgetTree,
) {
/// Subscribe to the modified `upstream` to mark the widget as dirty when the
/// `upstream` emits a modify event containing `ModifyScope::FRAMEWORK`.
///
/// # Panic
/// This method only works within a build process; otherwise, it will
/// result in a panic.
pub fn dirty_on(self, upstream: CloneableBoxOp<'static, ModifyScope, Infallible>) {
let tree = BuildCtx::get_mut().tree_mut();
let dirty_set = tree.dirty_set.clone();
let h = upstream
.filter(|b| b.contains(ModifyScope::FRAMEWORK))
Expand Down
6 changes: 1 addition & 5 deletions core/src/wrap_render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,20 @@ pub trait WrapRender {
Self: Sized + 'static,
{
child.on_build(move |id| {
let mut modifies = None;
let tree = BuildCtx::get_mut().tree_mut();
id.wrap_node(tree, |r| match this.try_into_value() {
Ok(this) => Box::new(RenderPair { wrapper: Box::new(this), host: r }),
Err(this) => {
let reader = match this.into_reader() {
Ok(r) => r,
Err(s) => {
modifies = Some(s.raw_modifies());
id.dirty_on(s.raw_modifies());
s.clone_reader()
}
};
Box::new(RenderPair { wrapper: Box::new(reader), host: r })
}
});
if let Some(modifies) = modifies {
id.dirty_subscribe(modifies, tree);
}
})
}
}
Expand Down
42 changes: 39 additions & 3 deletions widgets/src/layout/expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,23 @@ pub struct Expanded {
impl<'c> ComposeChild<'c> for Expanded {
type Child = Widget<'c>;
#[inline]
fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'c> {
child.try_unwrap_state_and_attach(this)
fn compose_child(this: impl StateWriter<Value = Self>, mut child: Self::Child) -> Widget<'c> {
let data: Box<dyn Query> = match this.try_into_value() {
Ok(this) => Box::new(Queryable(this)),
Err(this) => {
let modifies = this.raw_modifies();
child = child.on_build(|id| id.dirty_on(modifies));
Box::new(this)
}
};

child.attach_data(data)
}
}

#[cfg(test)]
mod tests {
use ribir_core::test_helper::*;
use ribir_core::{reset_test_env, test_helper::*};
use ribir_dev_helper::*;

use super::*;
Expand Down Expand Up @@ -88,4 +97,31 @@ mod tests {
LayoutCase::new(&[0, 5]).with_rect(ribir_geom::rect(100., 50., 50., 50.)),
LayoutCase::new(&[0, 6]).with_rect(ribir_geom::rect(150., 50., 200., 50.))
);

#[test]
fn modifies_flex() {
reset_test_env!();

let (flex, w_flex) = split_value(1f32);
let widget = fn_widget! {
let expanded = @Expanded { flex: 1. };
watch!(*$flex).subscribe(move |val| $expanded.write().flex = val);

@Row {
@ $expanded { @ { Void } }
@Expanded {
flex: 1.,
@ { Void }
}
@SizedBox { size: Size::new(100., 100.) }
}
};

let mut wnd = TestWindow::new_with_size(widget, Size::new(400., 100.));
wnd.draw_frame();
LayoutCase::expect_size(&wnd, &[0, 0], Size::new(150., 0.));
*w_flex.write() = 2.;
wnd.draw_frame();
LayoutCase::expect_size(&wnd, &[0, 0], Size::new(200., 0.));
}
}
Loading