mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Add async-callback channel to Cursive
And remove it from ProgressBar
This commit is contained in:
parent
04f961657f
commit
0643c50bd5
@ -4,7 +4,7 @@ use cursive::prelude::*;
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
fn main() {
|
||||
@ -16,15 +16,15 @@ fn main() {
|
||||
.content(Button::new("Start", |s| {
|
||||
// These two values will allow us to communicate.
|
||||
let value = Arc::new(AtomicUsize::new(0));
|
||||
let cb = Arc::new(Mutex::new(None));
|
||||
|
||||
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())
|
||||
.with_callback(cb.clone()))));
|
||||
.with_value(value.clone()))));
|
||||
|
||||
let cb = s.cb_sink().clone();
|
||||
|
||||
// Spawn a thread to process things in the background.
|
||||
thread::spawn(move || {
|
||||
@ -32,13 +32,15 @@ fn main() {
|
||||
thread::sleep(Duration::from_millis(20));
|
||||
value.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
*cb.lock().unwrap() = Some(Box::new(move |s| {
|
||||
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!"))
|
||||
.content(TextView::new("Phew, that was some \
|
||||
work!"))
|
||||
.button("Sure!", |s| s.quit()));
|
||||
}));
|
||||
}))
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
}))
|
||||
|
23
src/lib.rs
23
src/lib.rs
@ -97,6 +97,7 @@ pub use printer::Printer;
|
||||
|
||||
use backend::{Backend, NcursesBackend};
|
||||
|
||||
use std::sync::mpsc;
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
@ -126,6 +127,9 @@ pub struct Cursive {
|
||||
active_screen: ScreenId,
|
||||
|
||||
running: bool,
|
||||
|
||||
cb_source: mpsc::Receiver<Box<Fn(&mut Cursive) + Send>>,
|
||||
cb_sink: mpsc::Sender<Box<Fn(&mut Cursive) + Send>>,
|
||||
}
|
||||
|
||||
new_default!(Cursive);
|
||||
@ -143,6 +147,8 @@ impl Cursive {
|
||||
let theme = theme::load_default();
|
||||
// let theme = theme::load_theme("assets/style.toml").unwrap();
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
let mut res = Cursive {
|
||||
theme: theme,
|
||||
screens: Vec::new(),
|
||||
@ -150,6 +156,8 @@ impl Cursive {
|
||||
menubar: view::Menubar::new(),
|
||||
active_screen: 0,
|
||||
running: true,
|
||||
cb_source: rx,
|
||||
cb_sink: tx,
|
||||
};
|
||||
|
||||
res.screens.push(StackView::new());
|
||||
@ -157,6 +165,17 @@ impl Cursive {
|
||||
res
|
||||
}
|
||||
|
||||
/// Returns a sink for asynchronous callbacks.
|
||||
///
|
||||
/// Returns the sender part of a channel, that allows to send
|
||||
/// callbacks to `self` from other threads.
|
||||
///
|
||||
/// Callbacks will be executed in the order
|
||||
/// of arrival on the next event cycle.
|
||||
pub fn cb_sink(&self) -> &mpsc::Sender<Box<Fn(&mut Cursive) + Send>> {
|
||||
&self.cb_sink
|
||||
}
|
||||
|
||||
/// Selects the menubar
|
||||
pub fn select_menubar(&mut self) {
|
||||
self.menubar.take_focus(direction::Direction::none());
|
||||
@ -454,6 +473,10 @@ impl Cursive {
|
||||
|
||||
// And the big event loop begins!
|
||||
while self.running {
|
||||
if let Ok(cb) = self.cb_source.try_recv() {
|
||||
cb(self);
|
||||
}
|
||||
|
||||
// Do we need to redraw everytime?
|
||||
// Probably, actually.
|
||||
// TODO: Do we need to re-layout everytime?
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
@ -6,7 +6,6 @@ use {Cursive, Printer};
|
||||
use vec::Vec2;
|
||||
use align::HAlign;
|
||||
use direction::Orientation;
|
||||
use event::*;
|
||||
use theme::{ColorStyle, Effect};
|
||||
use view::View;
|
||||
|
||||
@ -18,7 +17,6 @@ pub struct ProgressBar {
|
||||
max: usize,
|
||||
value: Arc<AtomicUsize>,
|
||||
// TODO: use a Promise instead?
|
||||
callback: Option<Arc<Mutex<CbPromise>>>,
|
||||
label_maker: Box<Fn(usize, (usize, usize)) -> String>,
|
||||
}
|
||||
|
||||
@ -42,7 +40,6 @@ impl ProgressBar {
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: Arc::new(AtomicUsize::new(0)),
|
||||
callback: None,
|
||||
label_maker: Box::new(make_percentage),
|
||||
}
|
||||
}
|
||||
@ -53,14 +50,6 @@ impl ProgressBar {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the callback to follow.
|
||||
///
|
||||
/// Whenever `callback` is set, it will be called on the next event loop.
|
||||
pub fn with_callback(mut self, callback: Arc<Mutex<CbPromise>>) -> Self {
|
||||
self.callback = Some(callback);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the label generator.
|
||||
///
|
||||
/// The given function will be called with `(value, (min, max))`.
|
||||
@ -132,16 +121,6 @@ impl View for ProgressBar {
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(&mut self, _: Event) -> EventResult {
|
||||
if let Some(ref cb) = self.callback {
|
||||
if let Some(cb) = cb.lock().unwrap().take() {
|
||||
return EventResult::Consumed(Some(cb.into()));
|
||||
}
|
||||
}
|
||||
|
||||
EventResult::Ignored
|
||||
}
|
||||
|
||||
fn get_min_size(&mut self, size: Vec2) -> Vec2 {
|
||||
size.with_axis(Orientation::Vertical, 1)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user