Add user-data

This commit is contained in:
Alexandre Bury 2019-03-03 18:06:50 -08:00
parent 8562654553
commit 4f34e97f27
3 changed files with 77 additions and 0 deletions

View File

@ -11,6 +11,10 @@
- Updated to Rust 2018 (now requires rustc > 1.31) - Updated to Rust 2018 (now requires rustc > 1.31)
- Add a logging implementation (`logger::init()`) and a `DebugConsole` - Add a logging implementation (`logger::init()`) and a `DebugConsole`
(`cursive::toggle_debug_console()`) (`cursive::toggle_debug_console()`)
- Add user-data to Cursive.
- `Cursive::set_user_data()` can store some user-defined data structure.
- `Cursive::user_data()` and `Cursive::with_user_data()` can be used to
access the data.
- Add `StackView::remove_layer()` - Add `StackView::remove_layer()`
- Add `CircularFocus` view (and bring proper circular focus to dialogs) - Add `CircularFocus` view (and bring proper circular focus to dialogs)
- Add `HideableView::is_visible()` - Add `HideableView::is_visible()`

42
examples/user_data.rs Normal file
View File

@ -0,0 +1,42 @@
//! This example shows the usage of user data.
//!
//! This lets you attach data to the main `Cursive` root, which can simplify
//! communication in simple applications.
//!
//! `Cursive::set_user_data` is used to store or update the user data, while
//! `Cursive::user_data` and `Cursive::with_user_data` can access it, if they
//! know the exact type.
use cursive::views::Dialog;
use cursive::Cursive;
struct Data {
counter: u32,
}
fn main() {
let mut siv = Cursive::default();
// `Cursive::set_user_data` accepts any `T: Any`, which includes most
// owned types
siv.set_user_data(Data { counter: 0 });
siv.add_layer(
Dialog::text("This uses some user data!")
.title("User data example")
.button("Increment", |s| {
// `Cursive::with_user_data()` is an easy way to run a closure
// on the data.
s.with_user_data(|data: &mut Data| {
data.counter += 1;
});
})
.button("Show", |s| {
// `Cursive::user_data()` returns a reference to the data.
let value = s.user_data::<Data>().unwrap().counter;
s.add_layer(Dialog::info(format!("Current value: {}", value)));
})
.button("Quit", Cursive::quit),
);
siv.run();
}

View File

@ -43,6 +43,9 @@ pub struct Cursive {
cb_source: Receiver<Box<dyn CbFunc>>, cb_source: Receiver<Box<dyn CbFunc>>,
cb_sink: Sender<Box<dyn CbFunc>>, cb_sink: Sender<Box<dyn CbFunc>>,
// User-provided data.
user_data: Box<Any>,
} }
/// Identifies a screen in the cursive root. /// Identifies a screen in the cursive root.
@ -147,6 +150,7 @@ impl Cursive {
cb_source, cb_source,
cb_sink, cb_sink,
backend, backend,
user_data: Box::new(()),
} }
} }
@ -181,6 +185,33 @@ impl Cursive {
Self::new(backend::dummy::Backend::init) Self::new(backend::dummy::Backend::init)
} }
/// Sets some data to be stored in Cursive.
///
/// It can later on be accessed with `Cursive::user_data()`
pub fn set_user_data<T: Any>(&mut self, user_data: T) {
self.user_data = Box::new(user_data);
}
/// Attempts to access the user-provided data.
///
/// If some data was set previously with the same type, returns a reference to it.
/// If nothing was set or if the type is different, returns `None`.
pub fn user_data<T: Any>(&mut self) -> Option<&mut T> {
self.user_data.downcast_mut()
}
/// Runs the given closure on the stored user data, if any.
///
/// If no user data was supplied, or if the type is different, nothing will be run.
/// Otherwise, the result will be returned.
pub fn with_user_data<F, T, R>(&mut self, f: F) -> Option<R>
where
F: FnOnce(&mut T) -> R,
T: Any,
{
self.user_data().map(f)
}
/// Show the debug console. /// Show the debug console.
/// ///
/// Currently, this will show logs if [`::logger::init()`] was called. /// Currently, this will show logs if [`::logger::init()`] was called.