diff --git a/Cargo.toml b/Cargo.toml index 3e253ea..df49d5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,3 +36,7 @@ path = "examples/logs.rs" [[example]] name = "mutation" path = "examples/mutation.rs" + +[[example]] +name = "edit" +path = "examples/edit.rs" diff --git a/examples/edit.rs b/examples/edit.rs new file mode 100644 index 0000000..1c038ae --- /dev/null +++ b/examples/edit.rs @@ -0,0 +1,22 @@ +extern crate cursive; + +use cursive::{Cursive}; +use cursive::view::{Dialog,IdView,EditView,Selector,TextView}; + +fn main() { + let mut siv = Cursive::new(); + + siv.add_layer(Dialog::new(IdView::new("edit", EditView::new())) + .title("Enter your name") + .button("Ok", |s| { + let content = { + let name = s.find::(&Selector::Id("edit")).unwrap().get_content(); + format!("Hello {}", name) + }; + s.pop_layer(); + s.add_layer(Dialog::new(TextView::new(&content)) + .button("Quit", |s| s.quit())); + })); + + siv.run(); +} diff --git a/src/lib.rs b/src/lib.rs index f9f4e33..1394205 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,6 +156,10 @@ impl Cursive { self.screen_mut().add_layer(view); } + pub fn pop_layer(&mut self) { + self.screen_mut().pop_layer(); + } + // Handles a key event when it was ignored by the current view fn on_key_event(&mut self, ch: i32) { let cb = match self.global_callbacks.get(&ch) { diff --git a/src/view/dialog.rs b/src/view/dialog.rs index de4c9d2..8b0cbdd 100644 --- a/src/view/dialog.rs +++ b/src/view/dialog.rs @@ -1,11 +1,12 @@ use std::cmp::max; +use std::any::Any; use ncurses; use color; use ::{Cursive}; use event::EventResult; -use view::{View,SizeRequest,DimensionRequest}; +use view::{View,SizeRequest,DimensionRequest,Selector}; use view::{Button,SizedView}; use vec::{Vec2,Vec4,ToVec4}; use printer::Printer; @@ -215,4 +216,8 @@ impl View for Dialog { self.content.take_focus() } } + + fn find(&mut self, selector: &Selector) -> Option<&mut Any> { + self.content.find(selector) + } } diff --git a/src/view/edit_view.rs b/src/view/edit_view.rs new file mode 100644 index 0000000..b14af82 --- /dev/null +++ b/src/view/edit_view.rs @@ -0,0 +1,79 @@ +use ncurses; + +use color; +use view::{View}; +use event::EventResult; +use printer::Printer; + +/// Displays an editable text. +pub struct EditView { + content: String, + cursor: usize, + multiline: bool, +} + +impl EditView { + pub fn new() -> Self { + EditView { + content: String::new(), + cursor: 0, + multiline: false, + } + } + + pub fn set_content<'a>(&mut self, content: &'a str) { + self.content = content.to_string(); + } + + pub fn get_content(&self) -> &str { + &self.content + } + + pub fn content<'a>(mut self, content: &'a str) -> Self { + self.set_content(content); + self + } +} + +fn read_char(ch: i32) -> Option { + // Printable ascii range: 32-126 + if ch >= ' ' as i32 && ch <= '~' as i32 { + Some(ch as u8 as char) + } else { + None + } +} + +impl View for EditView { + fn draw(&mut self, printer: &Printer, focused: bool) { + let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE }; + printer.with_style(style, |printer| { + printer.print((0,0), &self.content); + }); + } + + fn take_focus(&mut self) -> bool { + true + } + + fn on_key_event(&mut self, ch: i32) -> EventResult { + + if let Some(ch) = read_char(ch) { + self.content.insert(self.cursor, ch); + self.cursor += 1; + return EventResult::Consumed(None); + } + + match ch { + ncurses::KEY_HOME => self.cursor = 0, + ncurses::KEY_END => self.cursor = self.content.len(), + ncurses::KEY_LEFT if self.cursor > 0 => self.cursor -= 1, + ncurses::KEY_RIGHT if self.cursor < self.content.len() => self.cursor += 1, + 127 if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); }, + 330 if self.cursor < self.content.len() => { self.content.remove(self.cursor); }, + _ => return EventResult::Ignored, + } + + EventResult::Consumed(None) + } +} diff --git a/src/view/id_view.rs b/src/view/id_view.rs index 8afbcfa..d632f7a 100644 --- a/src/view/id_view.rs +++ b/src/view/id_view.rs @@ -22,6 +22,7 @@ impl ViewWrapper for IdView { wrap_impl!(&self.view); fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> { + println!(" ID VIEWING "); match selector { &Selector::Id(id) if id == self.id => Some(&mut self.view), s => self.view.find(s), diff --git a/src/view/mod.rs b/src/view/mod.rs index 676b788..cb11185 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -12,6 +12,7 @@ mod sized_view; mod full_view; mod id_view; mod shadow_view; +mod edit_view; use std::any::Any; @@ -27,6 +28,7 @@ pub use self::view_wrapper::ViewWrapper; pub use self::full_view::FullView; pub use self::id_view::IdView; pub use self::shadow_view::ShadowView; +pub use self::edit_view::EditView; use event::EventResult; use vec::{Vec2,ToVec2};