mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-08-17 14:51:04 +02:00
refactor: recv_glib
dependency arrays
Adds a dependency array system to `recv_glib` which internally clones the passed deps and then passes by reference to the callback. This cleans up a lot of the big `{}` blocks full of `widget.clone()` and removes a lot of boilerplate. Yay!
This commit is contained in:
parent
beab26a37e
commit
9d18ce52f5
31 changed files with 539 additions and 517 deletions
107
src/channels.rs
107
src/channels.rs
|
@ -95,20 +95,29 @@ pub trait MpscReceiverExt<T> {
|
|||
/// Spawns a `GLib` future on the local thread, and calls `rx.recv()`
|
||||
/// in a loop, passing the message to `f`.
|
||||
///
|
||||
/// This allows use of `GObjects` and futures in the same context.
|
||||
fn recv_glib<F>(self, f: F)
|
||||
/// This allows use of `GObjects` and futures in the same context.#
|
||||
///
|
||||
/// `deps` is a single reference, or tuple of references of clonable objects,
|
||||
/// to be consumed inside the closure.
|
||||
/// This avoids needing to `element.clone()` everywhere.
|
||||
fn recv_glib<D, Fn>(self, deps: D, f: Fn)
|
||||
where
|
||||
F: FnMut(T) + 'static;
|
||||
D: Dependency,
|
||||
D::Target: Clone + 'static,
|
||||
Fn: FnMut(&D::Target, T) + 'static;
|
||||
}
|
||||
|
||||
impl<T: 'static> MpscReceiverExt<T> for mpsc::Receiver<T> {
|
||||
fn recv_glib<F>(mut self, mut f: F)
|
||||
fn recv_glib<D, Fn>(mut self, deps: D, mut f: Fn)
|
||||
where
|
||||
F: FnMut(T) + 'static,
|
||||
D: Dependency,
|
||||
D::Target: Clone + 'static,
|
||||
Fn: FnMut(&D::Target, T) + 'static,
|
||||
{
|
||||
let deps = deps.clone_content();
|
||||
glib::spawn_future_local(async move {
|
||||
while let Some(val) = self.recv().await {
|
||||
f(val);
|
||||
f(&deps, val);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -122,14 +131,22 @@ where
|
|||
/// in a loop, passing the message to `f`.
|
||||
///
|
||||
/// This allows use of `GObjects` and futures in the same context.
|
||||
fn recv_glib<F>(self, f: F)
|
||||
///
|
||||
/// `deps` is a single reference, or tuple of references of clonable objects,
|
||||
/// to be consumed inside the closure.
|
||||
/// This avoids needing to `element.clone()` everywhere.
|
||||
fn recv_glib<D, Fn>(self, deps: D, f: Fn)
|
||||
where
|
||||
F: FnMut(T) + 'static;
|
||||
D: Dependency,
|
||||
D::Target: Clone + 'static,
|
||||
Fn: FnMut(&D::Target, T) + 'static;
|
||||
|
||||
/// Like [`BroadcastReceiverExt::recv_glib`], but the closure must return a [`Future`].
|
||||
fn recv_glib_async<Fn, F>(self, f: Fn)
|
||||
fn recv_glib_async<D, Fn, F>(self, deps: D, f: Fn)
|
||||
where
|
||||
Fn: FnMut(T) -> F + 'static,
|
||||
D: Dependency,
|
||||
D::Target: Clone + 'static,
|
||||
Fn: FnMut(&D::Target, T) -> F + 'static,
|
||||
F: Future;
|
||||
}
|
||||
|
||||
|
@ -137,14 +154,17 @@ impl<T> BroadcastReceiverExt<T> for broadcast::Receiver<T>
|
|||
where
|
||||
T: Debug + Clone + 'static,
|
||||
{
|
||||
fn recv_glib<F>(mut self, mut f: F)
|
||||
fn recv_glib<D, Fn>(mut self, deps: D, mut f: Fn)
|
||||
where
|
||||
F: FnMut(T) + 'static,
|
||||
D: Dependency,
|
||||
D::Target: Clone + 'static,
|
||||
Fn: FnMut(&D::Target, T) + 'static,
|
||||
{
|
||||
let deps = deps.clone_content();
|
||||
glib::spawn_future_local(async move {
|
||||
loop {
|
||||
match self.recv().await {
|
||||
Ok(val) => f(val),
|
||||
Ok(val) => f(&deps, val),
|
||||
Err(broadcast::error::RecvError::Lagged(count)) => {
|
||||
tracing::warn!(
|
||||
"Channel lagged behind by {count}, this may result in unexpected or broken behaviour"
|
||||
|
@ -159,16 +179,19 @@ where
|
|||
});
|
||||
}
|
||||
|
||||
fn recv_glib_async<Fn, F>(mut self, mut f: Fn)
|
||||
fn recv_glib_async<D, Fn, F>(mut self, deps: D, mut f: Fn)
|
||||
where
|
||||
Fn: FnMut(T) -> F + 'static,
|
||||
D: Dependency,
|
||||
D::Target: Clone + 'static,
|
||||
Fn: FnMut(&D::Target, T) -> F + 'static,
|
||||
F: Future,
|
||||
{
|
||||
let deps = deps.clone_content();
|
||||
glib::spawn_future_local(async move {
|
||||
loop {
|
||||
match self.recv().await {
|
||||
Ok(val) => {
|
||||
f(val).await;
|
||||
f(&deps, val).await;
|
||||
}
|
||||
Err(broadcast::error::RecvError::Lagged(count)) => {
|
||||
tracing::warn!(
|
||||
|
@ -184,3 +207,55 @@ where
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// `recv_glib` callback dependency
|
||||
/// or dependency tuple.
|
||||
pub trait Dependency: Clone {
|
||||
type Target;
|
||||
|
||||
fn clone_content(&self) -> Self::Target;
|
||||
}
|
||||
|
||||
impl Dependency for () {
|
||||
type Target = ();
|
||||
|
||||
fn clone_content(&self) -> Self::Target {}
|
||||
}
|
||||
|
||||
impl<'a, T> Dependency for &'a T
|
||||
where
|
||||
T: Clone + 'a,
|
||||
{
|
||||
type Target = T;
|
||||
|
||||
fn clone_content(&self) -> T {
|
||||
T::clone(self)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_dependency {
|
||||
($($idx:tt $t:ident),+) => {
|
||||
impl<'a, $($t),+> Dependency for ($(&'a $t),+)
|
||||
where
|
||||
$($t: Clone + 'a),+
|
||||
{
|
||||
type Target = ($($t),+);
|
||||
|
||||
fn clone_content(&self) -> Self::Target {
|
||||
($(self.$idx.clone()),+)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_dependency!(0 T1, 1 T2);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6, 6 T7);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6, 6 T7, 7 T8);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6, 6 T7, 7 T8, 8 T9);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6, 6 T7, 7 T8, 8 T9, 9 T10);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6, 6 T7, 7 T8, 8 T9, 9 T10, 10 T11);
|
||||
impl_dependency!(0 T1, 1 T2, 2 T3, 3 T4, 4 T5, 5 T6, 6 T7, 7 T8, 8 T9, 9 T10, 10 T11, 11 T12);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue