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

Feat/build variant #690

Merged
merged 4 commits into from
Jan 14, 2025
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
18 changes: 13 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,20 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he

- **core**: The `Render::dirty_phase` method has been added to allow widgets to mark only the paint phase as dirty when it is modified. (#689 @M-Adoo)
- **core**: Supports `Provider` to dirty the tree if it's a state writer. (#689 @M-Adoo)
- **core**: Added the built-in field `providers` to provide data to its descendants. (#690 @M-Adoo)
- **core**: Added `Variant` to support building widgets with variables across `Providers`. (#690 @M-Adoo)
- **macros**: Added the `part_reader!` macro to generate a partial reader from a reference of a reader. (#688 @M-Adoo)
- **macros**: The `simple_declare` now supports the `stateless` meta attribute, `#[simple_declare(stateless)]`. (#688 @M-Adoo)

### Fixed

- **Core**: `PartData` allows the use of a reference to create a write reference, which is unsafe. Introduce `PartRef` and `PartMut` to replace it. (#690 @M-Adoo)


### Breading

- **core**: Removed `PartData`. (#690 @M-Adoo)

## [0.4.0-alpha.22] - 2025-01-08

### Fixed
Expand Down Expand Up @@ -289,10 +300,7 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he
```rust
let state = Stateful::value(0132);
providers!{
providers: smallvec![
Provider::new(state.clone_writer()),
Provider::value_of_state(state)
],
providers: [Provider::value_of_reader(state)],
@SizedBox {
size: Size::new(1.,1.),
on_tap: |e| {
Expand All @@ -303,7 +311,7 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he
@Text {
text: {
// Access the provider in any descendants
let v = Provider::of::<Stateful<i32>>(ctx!());
let v = Provider::state_of::<Stateful<i32>>(BuildCtx::get());
let v = v.unwrap().clone_writer();
pipe!($v.to_string())
}
Expand Down
51 changes: 39 additions & 12 deletions core/src/builtin_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,9 @@ pub struct FatObj<T> {
painting_style: Option<State<PaintingStyleWidget>>,
text_style: Option<State<TextStyleWidget>>,
keep_alive: Option<State<KeepAlive>>,
tooltips: Option<State<Tooltips>>,
keep_alive_unsubscribe_handle: Option<Box<dyn Any>>,
tooltips: Option<State<Tooltips>>,
providers: Option<SmallVec<[Provider; 1]>>,
}

/// Create a function widget that uses an empty `FatObj` as the host object.
Expand Down Expand Up @@ -187,6 +188,7 @@ impl<T> FatObj<T> {
tooltips: self.tooltips,
keep_alive: self.keep_alive,
keep_alive_unsubscribe_handle: self.keep_alive_unsubscribe_handle,
providers: self.providers,
}
}

Expand Down Expand Up @@ -770,7 +772,7 @@ impl<T> FatObj<T> {
self.declare_builtin_init(v, Self::get_fitted_box_widget, |m, v| m.box_fit = v)
}

/// Initializes the painting style of this widget.
/// Provide a painting style to this widget.
pub fn painting_style<const M: usize>(self, v: impl DeclareInto<PaintingStyle, M>) -> Self {
self.declare_builtin_init(v, Self::get_painting_style_widget, |m, v| m.painting_style = v)
}
Expand Down Expand Up @@ -923,6 +925,16 @@ impl<T> FatObj<T> {
self
}

/// Initializes the providers of the widget.
pub fn providers(mut self, providers: impl Into<SmallVec<[Provider; 1]>>) -> Self {
if let Some(vec) = self.providers.as_mut() {
vec.extend(providers.into());
} else {
self.providers = Some(providers.into());
}
self
}

fn declare_builtin_init<V: 'static, B: 'static, const M: usize>(
mut self, init: impl DeclareInto<V, M>, get_builtin: impl FnOnce(&mut Self) -> &State<B>,
set_value: fn(&mut B, V),
Expand Down Expand Up @@ -964,7 +976,7 @@ where
}

impl<'a> FatObj<Widget<'a>> {
fn compose(self) -> Widget<'a> {
fn compose(mut self) -> Widget<'a> {
macro_rules! compose_builtin_widgets {
($host: ident + [$($field: ident),*]) => {
$(
Expand All @@ -974,19 +986,34 @@ impl<'a> FatObj<Widget<'a>> {
)*
};
}
macro_rules! consume_providers_widget {
($host: ident, + [$($field: ident: $w_ty: ty),*]) => {
$(
if let Some($field) = self.$field {
self
.providers
.get_or_insert_default()
.push(<$w_ty>::into_provider($field));
}
)*
};
}
let mut host = self.host;
consume_providers_widget!(host, + [
painting_style: PaintingStyleWidget,
text_style: TextStyleWidget
]);

compose_builtin_widgets!(
host + [track_id, padding, fitted_box, foreground, box_decoration, scrollable, layout_box]
);
if let Some(providers) = self.providers {
host = Providers::new(providers).with_child(host);
}

compose_builtin_widgets!(
host
+ [
track_id,
padding,
fitted_box,
foreground,
box_decoration,
painting_style,
text_style,
scrollable,
layout_box,
class,
constrained_box,
tooltips,
Expand Down
17 changes: 9 additions & 8 deletions core/src/builtin_widgets/painting_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ impl<'c> ComposeChild<'c> for PaintingStyleWidget {
type Child = Widget<'c>;

fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'c> {
// We need to provide the text style for the children to access.
let provider = match this.try_into_value() {
Providers::new([Self::into_provider(this)]).with_child(child)
}
}

impl PaintingStyleWidget {
pub fn into_provider(this: impl StateWriter<Value = Self>) -> Provider {
match this.try_into_value() {
Ok(this) => Provider::new(this.painting_style),
Err(this) => Provider::value_of_writer(
this.map_writer(|w| PartData::from_ref_mut(&mut w.painting_style)),
this.map_writer(|w| PartMut::new(&mut w.painting_style)),
Some(DirtyPhase::LayoutSubtree),
),
};

Providers::new([provider])
.with_child(child)
.into_widget()
}
}
}
Loading
Loading