mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-27 11:16:03 +00:00
Add RefCellView
Wraps a view and provide interior mutability
This commit is contained in:
parent
b63762d441
commit
b0193b0ebc
19
Cargo.toml
19
Cargo.toml
@ -1,11 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
authors = ["Alexandre Bury <alexandre.bury@gmail.com>"]
|
authors = ["Alexandre Bury <alexandre.bury@gmail.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
categories = ["command-line-interface", "gui"]
|
||||||
description = "A TUI (Text User Interface) library focused on ease-of-use."
|
description = "A TUI (Text User Interface) library focused on ease-of-use."
|
||||||
documentation = "https://gyscos.github.io/Cursive/cursive/index.html"
|
documentation = "https://gyscos.github.io/Cursive/cursive/index.html"
|
||||||
exclude = ["doc", "assets"]
|
exclude = ["doc", "assets"]
|
||||||
keywords = ["ncurses", "TUI", "UI"]
|
keywords = ["ncurses", "TUI", "UI"]
|
||||||
categories = ["command-line-interface", "gui"]
|
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
name = "cursive"
|
name = "cursive"
|
||||||
readme = "Readme.md"
|
readme = "Readme.md"
|
||||||
@ -13,7 +13,11 @@ repository = "https://github.com/gyscos/Cursive"
|
|||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "gyscos/Cursive" }
|
|
||||||
|
[badges.travis-ci]
|
||||||
|
repository = "gyscos/Cursive"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
|
||||||
[build-dependencies.skeptic]
|
[build-dependencies.skeptic]
|
||||||
optional = true
|
optional = true
|
||||||
@ -23,18 +27,19 @@ version = "0.6"
|
|||||||
chan = "0.1.18"
|
chan = "0.1.18"
|
||||||
num = "0.1"
|
num = "0.1"
|
||||||
odds = "0.2"
|
odds = "0.2"
|
||||||
|
owning_ref = "0.2.4"
|
||||||
toml = "0.2"
|
toml = "0.2"
|
||||||
unicode-segmentation = "1.0"
|
unicode-segmentation = "1.0"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
|
|
||||||
[dependencies.chan-signal]
|
|
||||||
optional = true
|
|
||||||
version = "0.1"
|
|
||||||
|
|
||||||
[dependencies.bear-lib-terminal]
|
[dependencies.bear-lib-terminal]
|
||||||
optional = true
|
optional = true
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
|
||||||
|
[dependencies.chan-signal]
|
||||||
|
optional = true
|
||||||
|
version = "0.1"
|
||||||
|
|
||||||
[dependencies.ncurses]
|
[dependencies.ncurses]
|
||||||
features = ["wide"]
|
features = ["wide"]
|
||||||
optional = true
|
optional = true
|
||||||
@ -55,8 +60,8 @@ skeptic = "0.6"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ncurses"]
|
default = ["ncurses"]
|
||||||
termion-backend = ["termion", "chan-signal"]
|
|
||||||
pancurses-backend = ["pancurses"]
|
pancurses-backend = ["pancurses"]
|
||||||
|
termion-backend = ["termion", "chan-signal"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "cursive"
|
name = "cursive"
|
||||||
|
@ -64,6 +64,7 @@ extern crate unicode_segmentation;
|
|||||||
extern crate unicode_width;
|
extern crate unicode_width;
|
||||||
extern crate odds;
|
extern crate odds;
|
||||||
extern crate num;
|
extern crate num;
|
||||||
|
extern crate owning_ref;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate chan;
|
extern crate chan;
|
||||||
|
@ -52,6 +52,7 @@ mod menu_popup;
|
|||||||
mod panel;
|
mod panel;
|
||||||
mod progress_bar;
|
mod progress_bar;
|
||||||
mod radio;
|
mod radio;
|
||||||
|
mod refcell_view;
|
||||||
mod select_view;
|
mod select_view;
|
||||||
mod slider_view;
|
mod slider_view;
|
||||||
mod shadow_view;
|
mod shadow_view;
|
||||||
@ -78,6 +79,7 @@ pub use self::menubar::Menubar;
|
|||||||
pub use self::panel::Panel;
|
pub use self::panel::Panel;
|
||||||
pub use self::progress_bar::{Counter, ProgressBar};
|
pub use self::progress_bar::{Counter, ProgressBar};
|
||||||
pub use self::radio::{RadioGroup, RadioButton};
|
pub use self::radio::{RadioGroup, RadioButton};
|
||||||
|
pub use self::refcell_view::{RefCellView, ViewRef};
|
||||||
pub use self::select_view::SelectView;
|
pub use self::select_view::SelectView;
|
||||||
pub use self::shadow_view::ShadowView;
|
pub use self::shadow_view::ShadowView;
|
||||||
pub use self::sized_view::SizedView;
|
pub use self::sized_view::SizedView;
|
||||||
|
49
src/views/refcell_view.rs
Normal file
49
src/views/refcell_view.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
|
||||||
|
use owning_ref::{RcRef, OwningHandle};
|
||||||
|
|
||||||
|
use std::cell::{RefCell, RefMut};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use view::{View, ViewWrapper};
|
||||||
|
|
||||||
|
/// Wrapper around a view to provide interior mutability.
|
||||||
|
pub struct RefCellView<V: View> {
|
||||||
|
view: Rc<RefCell<V>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutable reference to a view.
|
||||||
|
pub type ViewRef<V> = OwningHandle<RcRef<RefCell<V>>, RefMut<'static, V>>;
|
||||||
|
|
||||||
|
impl<V: View> RefCellView<V> {
|
||||||
|
/// Wraps `view` in a new `RefCellView`.
|
||||||
|
pub fn new(view: V) -> Self {
|
||||||
|
RefCellView { view: Rc::new(RefCell::new(view)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets mutable access to the inner view.
|
||||||
|
pub fn get_mut(&mut self) -> ViewRef<V> {
|
||||||
|
// TODO: return a standalone item (not tied to our lifetime)
|
||||||
|
// that bundles `self.view.clone()` and allow mutable reference to
|
||||||
|
// the inner view.
|
||||||
|
let cell_ref = RcRef::new(self.view.clone());
|
||||||
|
|
||||||
|
OwningHandle::new(cell_ref,
|
||||||
|
|x| unsafe { x.as_ref() }.unwrap().borrow_mut())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: View> ViewWrapper for RefCellView<T> {
|
||||||
|
type V = T;
|
||||||
|
|
||||||
|
fn with_view<F, R>(&self, f: F) -> R
|
||||||
|
where F: FnOnce(&Self::V) -> R
|
||||||
|
{
|
||||||
|
f(&*self.view.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_view_mut<F, R>(&mut self, f: F) -> R
|
||||||
|
where F: FnOnce(&mut Self::V) -> R
|
||||||
|
{
|
||||||
|
f(&mut *self.view.borrow_mut())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user