mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-10 03:10:41 +00:00
Add start
and with_task
to ProgressBar
This commit is contained in:
parent
eb6b5d5728
commit
8eb61e0239
@ -4,8 +4,6 @@ use cursive::prelude::*;
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
@ -14,37 +12,36 @@ fn main() {
|
||||
.title("Progress bar example")
|
||||
.padding((0, 0, 1, 1))
|
||||
.content(Button::new("Start", |s| {
|
||||
// These two values will allow us to communicate.
|
||||
let value = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
// Number of ticks
|
||||
let n_max = 1000;
|
||||
|
||||
s.pop_layer();
|
||||
s.add_layer(Panel::new(FullView::full_width(ProgressBar::new()
|
||||
.range(0, n_max)
|
||||
.with_value(value.clone()))));
|
||||
|
||||
// This is the callback channel
|
||||
let cb = s.cb_sink().clone();
|
||||
|
||||
// Spawn a thread to process things in the background.
|
||||
thread::spawn(move || {
|
||||
for _ in 0..n_max {
|
||||
thread::sleep(Duration::from_millis(20));
|
||||
value.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
cb.send(Box::new(move |s| {
|
||||
s.pop_layer();
|
||||
s.add_layer(Dialog::empty()
|
||||
.title("Work done!")
|
||||
.content(TextView::new("Phew, that was some \
|
||||
work!"))
|
||||
.button("Sure!", |s| s.quit()));
|
||||
}))
|
||||
.unwrap();
|
||||
});
|
||||
s.pop_layer();
|
||||
s.add_layer(Panel::new(FullView::full_width(
|
||||
ProgressBar::new()
|
||||
.range(0, n_max)
|
||||
.with_task(move |ticker| {
|
||||
// This closure will be called in a separate thread.
|
||||
for _ in 0..n_max {
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
// The ticker method increases the progress value
|
||||
ticker(1);
|
||||
}
|
||||
|
||||
}))
|
||||
.with_id("dialog"));
|
||||
// When we're done, send a callback through the channel
|
||||
cb.send(Box::new(move |s| {
|
||||
s.pop_layer();
|
||||
s.add_layer(Dialog::empty()
|
||||
.title("Work done!")
|
||||
.content(TextView::new("Phew!"))
|
||||
.button("Finally!", |s| s.quit()));
|
||||
}))
|
||||
.unwrap();
|
||||
})
|
||||
)));
|
||||
})));
|
||||
|
||||
siv.set_fps(30);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use std::thread;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use {Cursive, Printer};
|
||||
@ -18,6 +19,8 @@ pub struct ProgressBar {
|
||||
label_maker: Box<Fn(usize, (usize, usize)) -> String>,
|
||||
}
|
||||
|
||||
pub type Ticker = Box<Fn(usize) + Send>;
|
||||
|
||||
fn make_percentage(value: usize, (min, max): (usize, usize)) -> String {
|
||||
let percent = 101 * (value - min) / (1 + max - min);
|
||||
format!("{} %", percent)
|
||||
@ -43,11 +46,36 @@ impl ProgressBar {
|
||||
}
|
||||
|
||||
/// Sets the value to follow.
|
||||
///
|
||||
/// Use this to manually control the progress to display
|
||||
/// by directly modifying the value pointed to by `value`.
|
||||
pub fn with_value(mut self, value: Arc<AtomicUsize>) -> Self {
|
||||
self.value = value;
|
||||
self
|
||||
}
|
||||
|
||||
/// Starts a function in a separate thread, and monitor the progress.
|
||||
///
|
||||
/// `f` will be given a `Ticker` to increment the bar's progress.
|
||||
pub fn start<F: FnOnce(Ticker) + Send + 'static>(&mut self, f: F) {
|
||||
let value = self.value.clone();
|
||||
let ticker: Ticker = Box::new(move |ticks| {
|
||||
value.fetch_add(ticks, Ordering::Relaxed);
|
||||
});
|
||||
|
||||
thread::spawn(move || {
|
||||
f(ticker);
|
||||
});
|
||||
}
|
||||
|
||||
/// Starts a function in a separate thread, and monitor the progress.
|
||||
///
|
||||
/// Chainable variant.
|
||||
pub fn with_task<F: FnOnce(Ticker) + Send + 'static>(mut self, task: F) -> Self {
|
||||
self.start(task);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the label generator.
|
||||
///
|
||||
/// The given function will be called with `(value, (min, max))`.
|
||||
|
Loading…
Reference in New Issue
Block a user