mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-09 19:00:46 +00:00
Add selector by ID
This commit is contained in:
parent
77aae36836
commit
d9b56574d2
@ -32,3 +32,7 @@ path = "examples/dialog.rs"
|
||||
[[example]]
|
||||
name = "logs"
|
||||
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 view::View;
|
||||
use printer::Printer;
|
||||
use view::{StackView,ViewPath};
|
||||
use view::{StackView,ViewPath,Selector};
|
||||
|
||||
use event::{EventResult,Callback};
|
||||
|
||||
@ -132,16 +132,16 @@ impl Cursive {
|
||||
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.
|
||||
self.screen_mut().find(path)
|
||||
self.screen_mut().find(selector)
|
||||
}
|
||||
|
||||
/// 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,
|
||||
/// it returns None.
|
||||
pub fn find<V: View + Any>(&mut self, path: &ViewPath) -> Option<&mut V> {
|
||||
match self.find_any(path) {
|
||||
pub fn find<V: View + Any>(&mut self, selector: &Selector) -> Option<&mut V> {
|
||||
match self.find_any(selector) {
|
||||
None => None,
|
||||
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 sized_view;
|
||||
mod full_view;
|
||||
mod id_view;
|
||||
|
||||
use std::any::Any;
|
||||
|
||||
@ -23,11 +24,41 @@ pub use self::button::Button;
|
||||
pub use self::sized_view::SizedView;
|
||||
pub use self::view_wrapper::ViewWrapper;
|
||||
pub use self::full_view::FullView;
|
||||
pub use self::id_view::IdView;
|
||||
|
||||
use event::EventResult;
|
||||
use vec::{Vec2,ToVec2};
|
||||
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.
|
||||
#[derive(PartialEq,Clone,Copy)]
|
||||
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::any::Any;
|
||||
|
||||
use ncurses;
|
||||
|
||||
use color;
|
||||
use vec::Vec2;
|
||||
use view::{View,SizeRequest,DimensionRequest};
|
||||
use view::{View,SizeRequest,DimensionRequest,Selector};
|
||||
use event::EventResult;
|
||||
use printer::Printer;
|
||||
|
||||
@ -57,7 +58,7 @@ impl View for StackView {
|
||||
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_vline((x+w,y+1), h, ' ' as u64);
|
||||
|
||||
@ -115,4 +116,13 @@ impl View for StackView {
|
||||
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
|
||||
/// with the given width.
|
||||
fn get_num_lines(&self, max_width: usize) -> usize {
|
||||
|
@ -1,9 +1,14 @@
|
||||
use std::any::Any;
|
||||
|
||||
use vec::Vec2;
|
||||
use view::{View,SizeRequest};
|
||||
use view::{View,SizeRequest,Selector};
|
||||
use printer::Printer;
|
||||
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 {
|
||||
/// Get an immutable reference to the wrapped view, so that we can forward some calls to it.
|
||||
fn get_view(&self) -> &View;
|
||||
@ -34,6 +39,10 @@ pub trait ViewWrapper {
|
||||
fn wrap_take_focus(&mut self) -> bool {
|
||||
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 {
|
||||
@ -56,6 +65,10 @@ impl <T: ViewWrapper> View for T {
|
||||
fn take_focus(&mut self) -> bool {
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user