From a0154c59192fd7c1ec89e1bc52b93e7813f4d580 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 17 Apr 2018 03:13:01 +0300 Subject: [PATCH] lazy_load: Add the ability to execute a callbakc on finish When iteration of data is finished, None will be returned and the or_else() block will be executed. Now a callback can be passed that will be executd when the iteration/loading finishes. --- hammond-gtk/src/utils.rs | 25 ++++++++++++++++--------- hammond-gtk/src/widgets/episode.rs | 6 ++++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 3d54ef4..45f1618 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -33,9 +33,10 @@ use chrono::Duration; /// Lazy evaluates and loads widgets to the parent `container` widget. /// -/// Accepts an IntoIterator, `T`, as the source from which each widget +/// Accepts an `IntoIterator`, `data`, as the source from which each widget /// will be constructed. An `FnMut` function that returns the desired -/// widget should be passed as the widget `constructor`. +/// widget should be passed as the widget `constructor`. You can also specify +/// a `callback` that will be executed when the iteration finish. /// /// ```no_run /// # struct Message; @@ -50,7 +51,7 @@ use chrono::Duration; /// let messages: Vec = Vec::new(); /// let list = gtk::ListBox::new(); /// let constructor = |m| { MessageWidget::new(m).0}; -/// lazy_load(messages, list, constructor); +/// lazy_load(messages, list, constructor, || {}); /// ``` /// /// If you have already constructed the widgets and only want to @@ -61,37 +62,43 @@ use chrono::Duration; /// # use std::collections::binary_heap::BinaryHeap; /// let widgets: BinaryHeap = BinaryHeap::new(); /// let list = gtk::ListBox::new(); -/// lazy_load(widgets, list, |w| w); +/// lazy_load(widgets, list, |w| w, || {}); /// ``` -pub fn lazy_load(data: T, container: C, mut contructor: F) +pub fn lazy_load(data: T, container: C, mut contructor: F, callback: U) where T: IntoIterator + 'static, T::Item: 'static, C: ContainerExt + 'static, F: FnMut(T::Item) -> W + 'static, W: IsA, + U: Fn() + 'static, { let func = move |x| container.add(&contructor(x)); - lazy_load_full(data, func); + lazy_load_full(data, func, callback); } -/// Iterate over `data` and execute `func` using a `glib::idle_add()`. +/// Iterate over `data` and execute `func` using a `glib::idle_add()`, +/// when the iteration finishes, it executes `finish_callback`. /// /// This is a more flexible version of `lazy_load` with less constrains. /// If you just want to lazy add `widgets` to a `container` check if /// `lazy_load` fits your needs first. -pub fn lazy_load_full(data: T, mut func: F) +pub fn lazy_load_full(data: T, mut func: F, finish_callback: U) where T: IntoIterator + 'static, T::Item: 'static, F: FnMut(T::Item) + 'static, + U: Fn() + 'static, { let mut data = data.into_iter(); gtk::idle_add(move || { data.next() .map(|x| func(x)) .map(|_| glib::Continue(true)) - .unwrap_or(glib::Continue(false)) + .unwrap_or_else(|| { + finish_callback(); + glib::Continue(false) + }) }); } diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 4f35c43..bd50fff 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -399,9 +399,11 @@ pub fn episodes_listbox(pd: Arc, sender: Sender) -> Result return glib::Continue(false), }; - lazy_load(episodes, list.clone(), clone!(sender => move |ep| { + let constructor = clone!(sender => move |ep| { EpisodeWidget::new(ep, sender.clone()).container - })); + }); + + lazy_load(episodes, list.clone(), constructor, || {}); glib::Continue(false) }));