mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +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::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut siv = Cursive::new();
|
let mut siv = Cursive::new();
|
||||||
@ -14,37 +12,36 @@ fn main() {
|
|||||||
.title("Progress bar example")
|
.title("Progress bar example")
|
||||||
.padding((0, 0, 1, 1))
|
.padding((0, 0, 1, 1))
|
||||||
.content(Button::new("Start", |s| {
|
.content(Button::new("Start", |s| {
|
||||||
// These two values will allow us to communicate.
|
// Number of ticks
|
||||||
let value = Arc::new(AtomicUsize::new(0));
|
|
||||||
|
|
||||||
let n_max = 1000;
|
let n_max = 1000;
|
||||||
|
|
||||||
s.pop_layer();
|
// This is the callback channel
|
||||||
s.add_layer(Panel::new(FullView::full_width(ProgressBar::new()
|
|
||||||
.range(0, n_max)
|
|
||||||
.with_value(value.clone()))));
|
|
||||||
|
|
||||||
let cb = s.cb_sink().clone();
|
let cb = s.cb_sink().clone();
|
||||||
|
|
||||||
// Spawn a thread to process things in the background.
|
s.pop_layer();
|
||||||
thread::spawn(move || {
|
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 {
|
for _ in 0..n_max {
|
||||||
thread::sleep(Duration::from_millis(20));
|
thread::sleep(Duration::from_millis(5));
|
||||||
value.fetch_add(1, Ordering::Relaxed);
|
// The ticker method increases the progress value
|
||||||
|
ticker(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When we're done, send a callback through the channel
|
||||||
cb.send(Box::new(move |s| {
|
cb.send(Box::new(move |s| {
|
||||||
s.pop_layer();
|
s.pop_layer();
|
||||||
s.add_layer(Dialog::empty()
|
s.add_layer(Dialog::empty()
|
||||||
.title("Work done!")
|
.title("Work done!")
|
||||||
.content(TextView::new("Phew, that was some \
|
.content(TextView::new("Phew!"))
|
||||||
work!"))
|
.button("Finally!", |s| s.quit()));
|
||||||
.button("Sure!", |s| s.quit()));
|
|
||||||
}))
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
})
|
||||||
|
)));
|
||||||
}))
|
})));
|
||||||
.with_id("dialog"));
|
|
||||||
|
|
||||||
siv.set_fps(30);
|
siv.set_fps(30);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use std::thread;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use {Cursive, Printer};
|
use {Cursive, Printer};
|
||||||
@ -18,6 +19,8 @@ pub struct ProgressBar {
|
|||||||
label_maker: Box<Fn(usize, (usize, usize)) -> String>,
|
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 {
|
fn make_percentage(value: usize, (min, max): (usize, usize)) -> String {
|
||||||
let percent = 101 * (value - min) / (1 + max - min);
|
let percent = 101 * (value - min) / (1 + max - min);
|
||||||
format!("{} %", percent)
|
format!("{} %", percent)
|
||||||
@ -43,11 +46,36 @@ impl ProgressBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the value to follow.
|
/// 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 {
|
pub fn with_value(mut self, value: Arc<AtomicUsize>) -> Self {
|
||||||
self.value = value;
|
self.value = value;
|
||||||
self
|
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.
|
/// Sets the label generator.
|
||||||
///
|
///
|
||||||
/// The given function will be called with `(value, (min, max))`.
|
/// The given function will be called with `(value, (min, max))`.
|
||||||
|
Loading…
Reference in New Issue
Block a user