mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-27 11:16:03 +00:00
Add selector by ID
This commit is contained in:
parent
77aae36836
commit
d9b56574d2
@ -32,3 +32,7 @@ path = "examples/dialog.rs"
|
|||||||
[[example]]
|
[[example]]
|
||||||
name = "logs"
|
name = "logs"
|
||||||
path = "examples/logs.rs"
|
path = "examples/logs.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "mutation"
|
||||||
|
path = "examples/mutation.rs"
|
||||||
|
16
examples/mutation.rs
Normal file
16
examples/mutation.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
extern crate cursive;
|
||||||
|
|
||||||
|
use cursive::Cursive;
|
||||||
|
use cursive::view::{IdView,TextView,Dialog,Selector};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut siv = Cursive::new();
|
||||||
|
|
||||||
|
siv.add_layer(IdView::new("text", TextView::new("Aaahh\nAaaah\nAaaah\nAaaaah\nAaaaah\nAaaaah\nAaaaah")));
|
||||||
|
|
||||||
|
siv.add_layer(Dialog::new(TextView::new("Tak!"))
|
||||||
|
.button("Change", |s,_| s.find::<TextView>(&Selector::Id("text")).unwrap()
|
||||||
|
.set_content("Bleeeeh") ));
|
||||||
|
|
||||||
|
siv.run();
|
||||||
|
}
|
10
src/lib.rs
10
src/lib.rs
@ -41,7 +41,7 @@ use std::collections::HashMap;
|
|||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::View;
|
use view::View;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
use view::{StackView,ViewPath};
|
use view::{StackView,ViewPath,Selector};
|
||||||
|
|
||||||
use event::{EventResult,Callback};
|
use event::{EventResult,Callback};
|
||||||
|
|
||||||
@ -132,16 +132,16 @@ impl Cursive {
|
|||||||
self.active_screen = screen_id;
|
self.active_screen = screen_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_any(&mut self, path: &ViewPath) -> Option<&mut Any> {
|
fn find_any(&mut self, selector: &Selector) -> Option<&mut Any> {
|
||||||
// Internal find method that returns a Any object.
|
// Internal find method that returns a Any object.
|
||||||
self.screen_mut().find(path)
|
self.screen_mut().find(selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to find the view pointed to by the given path.
|
/// Tries to find the view pointed to by the given path.
|
||||||
/// If the view is not found, or if it is not of the asked type,
|
/// If the view is not found, or if it is not of the asked type,
|
||||||
/// it returns None.
|
/// it returns None.
|
||||||
pub fn find<V: View + Any>(&mut self, path: &ViewPath) -> Option<&mut V> {
|
pub fn find<V: View + Any>(&mut self, selector: &Selector) -> Option<&mut V> {
|
||||||
match self.find_any(path) {
|
match self.find_any(selector) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(b) => b.downcast_mut::<V>(),
|
Some(b) => b.downcast_mut::<V>(),
|
||||||
}
|
}
|
||||||
|
30
src/view/id_view.rs
Normal file
30
src/view/id_view.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
use view::{View,ViewWrapper,Selector};
|
||||||
|
|
||||||
|
/// Wrapper view that allows to select its content with a fixed string id.
|
||||||
|
pub struct IdView<T: View> {
|
||||||
|
view: T,
|
||||||
|
id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: View> IdView<T> {
|
||||||
|
/// Wraps the given view. It will be selectable with the given id.
|
||||||
|
pub fn new(id: &str, view: T) -> Self {
|
||||||
|
IdView {
|
||||||
|
view: view,
|
||||||
|
id: id.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: View + Any> ViewWrapper for IdView<T> {
|
||||||
|
wrap_impl!(&self.view);
|
||||||
|
|
||||||
|
fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> {
|
||||||
|
match selector {
|
||||||
|
&Selector::Id(id) if id == self.id => Some(&mut self.view),
|
||||||
|
s => self.view.find(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ mod dialog;
|
|||||||
mod button;
|
mod button;
|
||||||
mod sized_view;
|
mod sized_view;
|
||||||
mod full_view;
|
mod full_view;
|
||||||
|
mod id_view;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
@ -23,11 +24,41 @@ pub use self::button::Button;
|
|||||||
pub use self::sized_view::SizedView;
|
pub use self::sized_view::SizedView;
|
||||||
pub use self::view_wrapper::ViewWrapper;
|
pub use self::view_wrapper::ViewWrapper;
|
||||||
pub use self::full_view::FullView;
|
pub use self::full_view::FullView;
|
||||||
|
pub use self::id_view::IdView;
|
||||||
|
|
||||||
use event::EventResult;
|
use event::EventResult;
|
||||||
use vec::{Vec2,ToVec2};
|
use vec::{Vec2,ToVec2};
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
|
/// Main trait defining a view behaviour.
|
||||||
|
pub trait View {
|
||||||
|
/// Called when a key was pressed. Default implementation just ignores it.
|
||||||
|
fn on_key_event(&mut self, i32) -> EventResult { EventResult::Ignored }
|
||||||
|
|
||||||
|
/// Returns the minimum size the view requires under the given restrictions.
|
||||||
|
fn get_min_size(&self, SizeRequest) -> Vec2 { Vec2::new(1,1) }
|
||||||
|
|
||||||
|
/// Called once the size for this view has been decided, so it can
|
||||||
|
/// propagate the information to its children.
|
||||||
|
fn layout(&mut self, Vec2) { }
|
||||||
|
|
||||||
|
/// Draws the view with the given printer (includes bounds) and focus.
|
||||||
|
fn draw(&mut self, printer: &Printer, focused: bool);
|
||||||
|
|
||||||
|
/// Finds the view pointed to by the given path.
|
||||||
|
/// Returns None if the path doesn't lead to a view.
|
||||||
|
fn find(&mut self, &Selector) -> Option<&mut Any> { None }
|
||||||
|
|
||||||
|
/// This view is offered focus. Will it take it?
|
||||||
|
fn take_focus(&mut self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Selects a single view (if any) in the tree.
|
||||||
|
pub enum Selector<'a> {
|
||||||
|
Id(&'a str),
|
||||||
|
Path(&'a ViewPath),
|
||||||
|
}
|
||||||
|
|
||||||
/// Describe constraints on a view layout in one dimension.
|
/// Describe constraints on a view layout in one dimension.
|
||||||
#[derive(PartialEq,Clone,Copy)]
|
#[derive(PartialEq,Clone,Copy)]
|
||||||
pub enum DimensionRequest {
|
pub enum DimensionRequest {
|
||||||
@ -78,26 +109,4 @@ impl SizeRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Main trait defining a view behaviour.
|
|
||||||
pub trait View {
|
|
||||||
/// Called when a key was pressed. Default implementation just ignores it.
|
|
||||||
fn on_key_event(&mut self, i32) -> EventResult { EventResult::Ignored }
|
|
||||||
|
|
||||||
/// Returns the minimum size the view requires under the given restrictions.
|
|
||||||
fn get_min_size(&self, SizeRequest) -> Vec2 { Vec2::new(1,1) }
|
|
||||||
|
|
||||||
/// Called once the size for this view has been decided, so it can
|
|
||||||
/// propagate the information to its children.
|
|
||||||
fn layout(&mut self, Vec2) { }
|
|
||||||
|
|
||||||
/// Draws the view with the given printer (includes bounds) and focus.
|
|
||||||
fn draw(&mut self, printer: &Printer, focused: bool);
|
|
||||||
|
|
||||||
/// Finds the view pointed to by the given path.
|
|
||||||
/// Returns None if the path doesn't lead to a view.
|
|
||||||
fn find(&mut self, &ViewPath) -> Option<&mut Any> { None }
|
|
||||||
|
|
||||||
/// This view is offered focus. Will it take it?
|
|
||||||
fn take_focus(&mut self) -> bool { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use ncurses;
|
use ncurses;
|
||||||
|
|
||||||
use color;
|
use color;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View,SizeRequest,DimensionRequest};
|
use view::{View,SizeRequest,DimensionRequest,Selector};
|
||||||
use event::EventResult;
|
use event::EventResult;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ impl View for StackView {
|
|||||||
let y = (printer.size.y - h) / 2;
|
let y = (printer.size.y - h) / 2;
|
||||||
|
|
||||||
|
|
||||||
let printer = printer.style(color::SHADOW);
|
let printer = printer.style(color::HIGHLIGHT);
|
||||||
printer.print_hline((x+1,y+h), w, ' ' as u64);
|
printer.print_hline((x+1,y+h), w, ' ' as u64);
|
||||||
printer.print_vline((x+w,y+1), h, ' ' as u64);
|
printer.print_vline((x+w,y+1), h, ' ' as u64);
|
||||||
|
|
||||||
@ -115,4 +116,13 @@ impl View for StackView {
|
|||||||
Some(mut v) => v.view.take_focus()
|
Some(mut v) => v.view.take_focus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find(&mut self, selector: &Selector) -> Option<&mut Any> {
|
||||||
|
for layer in self.layers.iter_mut() {
|
||||||
|
if let Some(any) = layer.view.find(selector) {
|
||||||
|
return Some(any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,10 @@ impl TextView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_content(&mut self, content: &str) {
|
||||||
|
self.content = content.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the number of lines required to display the content
|
/// Returns the number of lines required to display the content
|
||||||
/// with the given width.
|
/// with the given width.
|
||||||
fn get_num_lines(&self, max_width: usize) -> usize {
|
fn get_num_lines(&self, max_width: usize) -> usize {
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View,SizeRequest};
|
use view::{View,SizeRequest,Selector};
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
use event::EventResult;
|
use event::EventResult;
|
||||||
|
|
||||||
/// Wrapper around a view. Can override some methods, forwards the others.
|
/// Generic wrapper around a view.
|
||||||
|
///
|
||||||
|
/// Default implementation forwards all calls to the child view.
|
||||||
|
/// Overrides some methods as desired.
|
||||||
pub trait ViewWrapper {
|
pub trait ViewWrapper {
|
||||||
/// Get an immutable reference to the wrapped view, so that we can forward some calls to it.
|
/// Get an immutable reference to the wrapped view, so that we can forward some calls to it.
|
||||||
fn get_view(&self) -> &View;
|
fn get_view(&self) -> &View;
|
||||||
@ -34,6 +39,10 @@ pub trait ViewWrapper {
|
|||||||
fn wrap_take_focus(&mut self) -> bool {
|
fn wrap_take_focus(&mut self) -> bool {
|
||||||
self.get_view_mut().take_focus()
|
self.get_view_mut().take_focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> {
|
||||||
|
self.get_view_mut().find(selector)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: ViewWrapper> View for T {
|
impl <T: ViewWrapper> View for T {
|
||||||
@ -56,6 +65,10 @@ impl <T: ViewWrapper> View for T {
|
|||||||
fn take_focus(&mut self) -> bool {
|
fn take_focus(&mut self) -> bool {
|
||||||
self.wrap_take_focus()
|
self.wrap_take_focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find(&mut self, selector: &Selector) -> Option<&mut Any> {
|
||||||
|
self.wrap_find(selector)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenient macro to implement to two methods required for the ViewWrapper trait.
|
/// Convenient macro to implement to two methods required for the ViewWrapper trait.
|
||||||
|
Loading…
Reference in New Issue
Block a user