Skip to content

Commit

Permalink
fix(core): 🐛 Added DeclarerWithSubscription to let Widget Expanded
Browse files Browse the repository at this point in the history
…accept pipe value
  • Loading branch information
wjian23 committed Dec 13, 2024
1 parent 7c2bb7b commit 32f4a58
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 7 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he

### Features

- **core**: Added `grab_pointer` to grabs all the pointer input. (#pr @wjian23)
- **core**: Added `grab_pointer` to grabs all the pointer input. (#pr @wjian23)

### Fixed
- **core**: fix mismatch of providers (#pr @wjian23)
- **core**: fix mismatch of providers. (#pr @wjian23)
- **core**: Added DeclarerWithSubscription to let Widget `Expanded` accept pipe value. (#pr @wjian23)

## [0.4.0-alpha.18] - 2024-12-11

Expand Down
68 changes: 68 additions & 0 deletions core/src/builtin_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
pub mod key;
mod painting_style;
use std::ops::DerefMut;

pub use key::{Key, KeyWidget};
pub use painting_style::*;
pub mod image_widget;
Expand Down Expand Up @@ -999,3 +1001,69 @@ impl<T> std::ops::DerefMut for FatObj<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.host }
}

/// DeclarerWithSubscription, a declarer with subscriptions
///
/// Used to wraps a declarer to make it the widget auto unsubscribe when
/// disposed. Normally you should not use this directly, most Widget types
/// derive with Declare attribute has support builtin widgets has the ability
/// of unsubscribing when disposed.
pub struct DeclarerWithSubscription<T> {
inner: T,
subscribes: Vec<BoxSubscription<'static>>,
}

impl<T> DeclarerWithSubscription<T> {
pub fn new(host: T, subscribes: Vec<BoxSubscription<'static>>) -> Self {
Self { inner: host, subscribes }
}
}

impl<T> Deref for DeclarerWithSubscription<T> {
type Target = T;

fn deref(&self) -> &Self::Target { &self.inner }
}

impl<T> DerefMut for DeclarerWithSubscription<T> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner }
}

impl<T> DeclarerWithSubscription<T> {
fn map<M>(self, f: impl FnOnce(T) -> M) -> DeclarerWithSubscription<M> {
DeclarerWithSubscription { inner: f(self.inner), subscribes: self.subscribes }
}
}

impl<'w, T, const M: usize> IntoWidgetStrict<'w, M> for DeclarerWithSubscription<T>
where
T: IntoWidget<'w, M>,
{
fn into_widget_strict(self) -> Widget<'w> {
let DeclarerWithSubscription { inner: host, subscribes } = self;
let w = host.into_widget();
if subscribes.is_empty() {
w
} else {
fn_widget! {
let w = FatObj::new(w);
@ $w {
on_disposed: move |_| {
subscribes.into_iter().for_each(|u| u.unsubscribe());
}
}
}
.into_widget()
}
}
}

impl<'w, T, C, const N: usize, const M: usize> WithChild<'w, C, N, M>
for DeclarerWithSubscription<T>
where
T: WithChild<'w, C, N, M> + 'w,
C: 'w,
{
type Target = DeclarerWithSubscription<T::Target>;
fn with_child(self, c: C) -> Self::Target { self.map(|w| w.with_child(c)) }
}
46 changes: 41 additions & 5 deletions widgets/src/layout/expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,51 @@ use ribir_core::prelude::*;
/// available space. If multiple children are expanded, the available space is
/// divided among them according to the flex factor.
#[derive(Clone, PartialEq)]
// `Expand` should not support `FatObj`, as this may cause the `Expanded` to be invisible to its
// parent. `@Expanded { margin: EdgeInsets::all(10.) }` actually expands as `@Margin { @Expanded {
// .. } }`.
#[simple_declare]
// `Expand` should not support `FatObj`, as this may cause the `Expanded` to be
// invisible to its parent. `@Expanded { margin: EdgeInsets::all(10.) }`
// actually expands as `@Margin { @Expanded { .. } }`.
pub struct Expanded {
#[declare(default = 1.)]
pub flex: f32,
}

impl Default for Expanded {
fn default() -> Self { Self { flex: 1. } }
}

#[derive(Default)]
pub struct FlexDeclarer {
flex: Option<DeclareInit<f32>>,
}

impl FlexDeclarer {
pub fn flex<const M: u8>(mut self, flex: impl DeclareInto<f32, M>) -> Self {
self.flex = Some(flex.declare_into());
self
}
}

impl Declare for Expanded {
type Builder = FlexDeclarer;

fn declarer() -> Self::Builder { FlexDeclarer::default() }
}

impl ObjDeclarer for FlexDeclarer {
type Target = DeclarerWithSubscription<State<Expanded>>;

fn finish(self) -> Self::Target {
let (v, u) = self.flex.map(|v| v.unzip()).unwrap_or((1., None));
let host = State::value(Expanded { flex: v });
let mut subscribes = Vec::new();
if let Some(o) = u {
let host = host.clone_writer();
let u = o.subscribe(move |(_, v)| host.write().flex = v);
subscribes.push(u)
}
DeclarerWithSubscription::new(host, subscribes)
}
}

impl<'c> ComposeChild<'c> for Expanded {
type Child = Widget<'c>;
#[inline]
Expand Down

0 comments on commit 32f4a58

Please sign in to comment.