This commit is contained in:
Alexandre Bury 2017-12-30 23:03:42 +01:00
parent 799ec812e4
commit e4cd68a4eb
41 changed files with 526 additions and 557 deletions

View File

@ -21,10 +21,9 @@ fn main() {
.fixed_width(20), .fixed_width(20),
) )
.button("Ok", |s| { .button("Ok", |s| {
let name = s.call_on_id( let name = s.call_on_id("name", |view: &mut EditView| {
"name", view.get_content()
|view: &mut EditView| view.get_content(), }).unwrap();
).unwrap();
show_popup(s, &name); show_popup(s, &name);
}), }),
); );

View File

@ -4,7 +4,6 @@ use cursive::{Cursive, Printer};
use cursive::event::{Event, EventResult}; use cursive::event::{Event, EventResult};
use cursive::traits::*; use cursive::traits::*;
fn main() { fn main() {
let mut siv = Cursive::new(); let mut siv = Cursive::new();

View File

@ -17,16 +17,16 @@ fn main() {
.child("Name", EditView::new().fixed_width(10)) .child("Name", EditView::new().fixed_width(10))
.child( .child(
"Receive spam?", "Receive spam?",
Checkbox::new().on_change( Checkbox::new().on_change(|s, checked| {
|s, checked| for name in &["email1", "email2"] { for name in &["email1", "email2"] {
s.call_on_id(name, |view: &mut EditView| { s.call_on_id(name, |view: &mut EditView| {
view.set_enabled(checked) view.set_enabled(checked)
}); });
if checked { if checked {
s.focus_id("email1").unwrap(); s.focus_id("email1").unwrap();
} }
}, }
), }),
) )
.child( .child(
"Email", "Email",
@ -55,11 +55,13 @@ fn main() {
.item_str("31-40") .item_str("31-40")
.item_str("41+"), .item_str("41+"),
) )
.with(|list| for i in 0..50 { .with(|list| {
list.add_child( for i in 0..50 {
&format!("Item {}", i), list.add_child(
EditView::new(), &format!("Item {}", i),
); EditView::new(),
);
}
}), }),
), ),
); );

View File

@ -31,7 +31,6 @@ fn main() {
siv.run(); siv.run();
} }
fn show_options(siv: &mut Cursive) { fn show_options(siv: &mut Cursive) {
siv.add_layer( siv.add_layer(
Dialog::new() Dialog::new()

View File

@ -16,10 +16,9 @@ fn main() {
.value(7) .value(7)
.on_change(|s, v| { .on_change(|s, v| {
let title = format!("[ {} ]", v); let title = format!("[ {} ]", v);
s.call_on_id( s.call_on_id("dialog", |view: &mut Dialog| {
"dialog", view.set_title(title)
|view: &mut Dialog| view.set_title(title), });
);
}) })
.on_enter(|s, v| { .on_enter(|s, v| {
s.pop_layer(); s.pop_layer();

View File

@ -1,11 +1,9 @@
extern crate cursive; extern crate cursive;
use cursive::Cursive; use cursive::Cursive;
use cursive::theme::{Color, Theme}; use cursive::theme::{Color, Theme};
use cursive::views::TextView; use cursive::views::TextView;
fn custom_theme_from_cursive(siv: &Cursive) -> Theme { fn custom_theme_from_cursive(siv: &Cursive) -> Theme {
let mut theme = siv.current_theme().clone(); let mut theme = siv.current_theme().clone();
theme.colors.background = Color::TerminalDefault; theme.colors.background = Color::TerminalDefault;

View File

@ -25,45 +25,45 @@ impl Concrete {
&mut self, kc: KeyCode, shift: bool, ctrl: bool &mut self, kc: KeyCode, shift: bool, ctrl: bool
) -> Event { ) -> Event {
match kc { match kc {
KeyCode::F1 | KeyCode::F1
KeyCode::F2 | | KeyCode::F2
KeyCode::F3 | | KeyCode::F3
KeyCode::F4 | | KeyCode::F4
KeyCode::F5 | | KeyCode::F5
KeyCode::F6 | | KeyCode::F6
KeyCode::F7 | | KeyCode::F7
KeyCode::F8 | | KeyCode::F8
KeyCode::F9 | | KeyCode::F9
KeyCode::F10 | | KeyCode::F10
KeyCode::F11 | | KeyCode::F11
KeyCode::F12 | | KeyCode::F12
KeyCode::NumEnter | | KeyCode::NumEnter
KeyCode::Enter | | KeyCode::Enter
KeyCode::Escape | | KeyCode::Escape
KeyCode::Backspace | | KeyCode::Backspace
KeyCode::Tab | | KeyCode::Tab
KeyCode::Pause | | KeyCode::Pause
KeyCode::Insert | | KeyCode::Insert
KeyCode::Home | | KeyCode::Home
KeyCode::PageUp | | KeyCode::PageUp
KeyCode::Delete | | KeyCode::Delete
KeyCode::End | | KeyCode::End
KeyCode::PageDown | | KeyCode::PageDown
KeyCode::Right | | KeyCode::Right
KeyCode::Left | | KeyCode::Left
KeyCode::Down | | KeyCode::Down
KeyCode::Up => match (shift, ctrl) { | KeyCode::Up => match (shift, ctrl) {
(true, true) => Event::CtrlShift(blt_keycode_to_key(kc)), (true, true) => Event::CtrlShift(blt_keycode_to_key(kc)),
(true, false) => Event::Shift(blt_keycode_to_key(kc)), (true, false) => Event::Shift(blt_keycode_to_key(kc)),
(false, true) => Event::Ctrl(blt_keycode_to_key(kc)), (false, true) => Event::Ctrl(blt_keycode_to_key(kc)),
(false, false) => Event::Key(blt_keycode_to_key(kc)), (false, false) => Event::Key(blt_keycode_to_key(kc)),
}, },
// TODO: mouse support // TODO: mouse support
KeyCode::MouseLeft | KeyCode::MouseLeft
KeyCode::MouseRight | | KeyCode::MouseRight
KeyCode::MouseMiddle | | KeyCode::MouseMiddle
KeyCode::MouseFourth | | KeyCode::MouseFourth
KeyCode::MouseFifth => blt_keycode_to_mouse_button(kc) | KeyCode::MouseFifth => blt_keycode_to_mouse_button(kc)
.map(|btn| { .map(|btn| {
self.buttons_pressed.insert(btn); self.buttons_pressed.insert(btn);
Event::Mouse { Event::Mouse {
@ -73,69 +73,69 @@ impl Concrete {
} }
}) })
.unwrap_or(Event::Unknown(vec![])), .unwrap_or(Event::Unknown(vec![])),
KeyCode::A | KeyCode::A
KeyCode::B | | KeyCode::B
KeyCode::C | | KeyCode::C
KeyCode::D | | KeyCode::D
KeyCode::E | | KeyCode::E
KeyCode::F | | KeyCode::F
KeyCode::G | | KeyCode::G
KeyCode::H | | KeyCode::H
KeyCode::I | | KeyCode::I
KeyCode::J | | KeyCode::J
KeyCode::K | | KeyCode::K
KeyCode::L | | KeyCode::L
KeyCode::M | | KeyCode::M
KeyCode::N | | KeyCode::N
KeyCode::O | | KeyCode::O
KeyCode::P | | KeyCode::P
KeyCode::Q | | KeyCode::Q
KeyCode::R | | KeyCode::R
KeyCode::S | | KeyCode::S
KeyCode::T | | KeyCode::T
KeyCode::U | | KeyCode::U
KeyCode::V | | KeyCode::V
KeyCode::W | | KeyCode::W
KeyCode::X | | KeyCode::X
KeyCode::Y | | KeyCode::Y
KeyCode::Z | | KeyCode::Z
KeyCode::Row1 | | KeyCode::Row1
KeyCode::Row2 | | KeyCode::Row2
KeyCode::Row3 | | KeyCode::Row3
KeyCode::Row4 | | KeyCode::Row4
KeyCode::Row5 | | KeyCode::Row5
KeyCode::Row6 | | KeyCode::Row6
KeyCode::Row7 | | KeyCode::Row7
KeyCode::Row8 | | KeyCode::Row8
KeyCode::Row9 | | KeyCode::Row9
KeyCode::Row0 | | KeyCode::Row0
KeyCode::Grave | | KeyCode::Grave
KeyCode::Minus | | KeyCode::Minus
KeyCode::Equals | | KeyCode::Equals
KeyCode::LeftBracket | | KeyCode::LeftBracket
KeyCode::RightBracket | | KeyCode::RightBracket
KeyCode::Backslash | | KeyCode::Backslash
KeyCode::Semicolon | | KeyCode::Semicolon
KeyCode::Apostrophe | | KeyCode::Apostrophe
KeyCode::Comma | | KeyCode::Comma
KeyCode::Period | | KeyCode::Period
KeyCode::Slash | | KeyCode::Slash
KeyCode::Space | | KeyCode::Space
KeyCode::NumDivide | | KeyCode::NumDivide
KeyCode::NumMultiply | | KeyCode::NumMultiply
KeyCode::NumMinus | | KeyCode::NumMinus
KeyCode::NumPlus | | KeyCode::NumPlus
KeyCode::NumPeriod | | KeyCode::NumPeriod
KeyCode::Num1 | | KeyCode::Num1
KeyCode::Num2 | | KeyCode::Num2
KeyCode::Num3 | | KeyCode::Num3
KeyCode::Num4 | | KeyCode::Num4
KeyCode::Num5 | | KeyCode::Num5
KeyCode::Num6 | | KeyCode::Num6
KeyCode::Num7 | | KeyCode::Num7
KeyCode::Num8 | | KeyCode::Num8
KeyCode::Num9 | | KeyCode::Num9
KeyCode::Num0 => if ctrl { | KeyCode::Num0 => if ctrl {
Event::CtrlChar(blt_keycode_to_char(kc, shift)) Event::CtrlChar(blt_keycode_to_char(kc, shift))
} else { } else {
Event::Char(blt_keycode_to_char(kc, shift)) Event::Char(blt_keycode_to_char(kc, shift))
@ -200,9 +200,10 @@ impl backend::Backend for Concrete {
} }
fn clear(&self, color: Color) { fn clear(&self, color: Color) {
terminal::set_background( terminal::set_background(colour_to_blt_colour(
colour_to_blt_colour(color, ColorRole::Background), color,
); ColorRole::Background,
));
terminal::clear(None); terminal::clear(None);
} }

View File

@ -89,12 +89,10 @@ impl Concrete {
| ncurses::BUTTON_CTRL) | ncurses::BUTTON_CTRL)
as mmask_t; as mmask_t;
let make_event = |event| { let make_event = |event| Event::Mouse {
Event::Mouse { offset: Vec2::zero(),
offset: Vec2::zero(), position: Vec2::new(mevent.x as usize, mevent.y as usize),
position: Vec2::new(mevent.x as usize, mevent.y as usize), event: event,
event: event,
}
}; };
if mevent.bstate == ncurses::REPORT_MOUSE_POSITION as mmask_t { if mevent.bstate == ncurses::REPORT_MOUSE_POSITION as mmask_t {
@ -214,7 +212,6 @@ impl backend::Backend for Concrete {
ncurses::endwin(); ncurses::endwin();
} }
fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) { fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) {
let current = self.current_style.get(); let current = self.current_style.get();
if current != colors { if current != colors {
@ -284,31 +281,31 @@ impl backend::Backend for Concrete {
/// Returns the Key enum corresponding to the given ncurses event. /// Returns the Key enum corresponding to the given ncurses event.
fn get_mouse_button(bare_event: i32) -> MouseButton { fn get_mouse_button(bare_event: i32) -> MouseButton {
match bare_event { match bare_event {
ncurses::BUTTON1_RELEASED | ncurses::BUTTON1_RELEASED
ncurses::BUTTON1_PRESSED | | ncurses::BUTTON1_PRESSED
ncurses::BUTTON1_CLICKED | | ncurses::BUTTON1_CLICKED
ncurses::BUTTON1_DOUBLE_CLICKED | | ncurses::BUTTON1_DOUBLE_CLICKED
ncurses::BUTTON1_TRIPLE_CLICKED => MouseButton::Left, | ncurses::BUTTON1_TRIPLE_CLICKED => MouseButton::Left,
ncurses::BUTTON2_RELEASED | ncurses::BUTTON2_RELEASED
ncurses::BUTTON2_PRESSED | | ncurses::BUTTON2_PRESSED
ncurses::BUTTON2_CLICKED | | ncurses::BUTTON2_CLICKED
ncurses::BUTTON2_DOUBLE_CLICKED | | ncurses::BUTTON2_DOUBLE_CLICKED
ncurses::BUTTON2_TRIPLE_CLICKED => MouseButton::Middle, | ncurses::BUTTON2_TRIPLE_CLICKED => MouseButton::Middle,
ncurses::BUTTON3_RELEASED | ncurses::BUTTON3_RELEASED
ncurses::BUTTON3_PRESSED | | ncurses::BUTTON3_PRESSED
ncurses::BUTTON3_CLICKED | | ncurses::BUTTON3_CLICKED
ncurses::BUTTON3_DOUBLE_CLICKED | | ncurses::BUTTON3_DOUBLE_CLICKED
ncurses::BUTTON3_TRIPLE_CLICKED => MouseButton::Right, | ncurses::BUTTON3_TRIPLE_CLICKED => MouseButton::Right,
ncurses::BUTTON4_RELEASED | ncurses::BUTTON4_RELEASED
ncurses::BUTTON4_PRESSED | | ncurses::BUTTON4_PRESSED
ncurses::BUTTON4_CLICKED | | ncurses::BUTTON4_CLICKED
ncurses::BUTTON4_DOUBLE_CLICKED | | ncurses::BUTTON4_DOUBLE_CLICKED
ncurses::BUTTON4_TRIPLE_CLICKED => MouseButton::Button4, | ncurses::BUTTON4_TRIPLE_CLICKED => MouseButton::Button4,
ncurses::BUTTON5_RELEASED | ncurses::BUTTON5_RELEASED
ncurses::BUTTON5_PRESSED | | ncurses::BUTTON5_PRESSED
ncurses::BUTTON5_CLICKED | | ncurses::BUTTON5_CLICKED
ncurses::BUTTON5_DOUBLE_CLICKED | | ncurses::BUTTON5_DOUBLE_CLICKED
ncurses::BUTTON5_TRIPLE_CLICKED => MouseButton::Button5, | ncurses::BUTTON5_TRIPLE_CLICKED => MouseButton::Button5,
_ => MouseButton::Other, _ => MouseButton::Other,
} }
} }
@ -328,36 +325,36 @@ where
match bare_event { match bare_event {
ncurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp), ncurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp),
ncurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown), ncurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown),
ncurses::BUTTON1_RELEASED | ncurses::BUTTON1_RELEASED
ncurses::BUTTON2_RELEASED | | ncurses::BUTTON2_RELEASED
ncurses::BUTTON3_RELEASED | | ncurses::BUTTON3_RELEASED
ncurses::BUTTON4_RELEASED | | ncurses::BUTTON4_RELEASED
ncurses::BUTTON5_RELEASED => f(MouseEvent::Release(button)), | ncurses::BUTTON5_RELEASED => f(MouseEvent::Release(button)),
ncurses::BUTTON1_PRESSED | ncurses::BUTTON1_PRESSED
ncurses::BUTTON2_PRESSED | | ncurses::BUTTON2_PRESSED
ncurses::BUTTON3_PRESSED => f(MouseEvent::Press(button)), | ncurses::BUTTON3_PRESSED => f(MouseEvent::Press(button)),
ncurses::BUTTON1_CLICKED | ncurses::BUTTON1_CLICKED
ncurses::BUTTON2_CLICKED | | ncurses::BUTTON2_CLICKED
ncurses::BUTTON3_CLICKED | | ncurses::BUTTON3_CLICKED
ncurses::BUTTON4_CLICKED | | ncurses::BUTTON4_CLICKED
ncurses::BUTTON5_CLICKED => { | ncurses::BUTTON5_CLICKED => {
f(MouseEvent::Press(button)); f(MouseEvent::Press(button));
f(MouseEvent::Release(button)); f(MouseEvent::Release(button));
} }
// Well, we disabled click detection // Well, we disabled click detection
ncurses::BUTTON1_DOUBLE_CLICKED | ncurses::BUTTON1_DOUBLE_CLICKED
ncurses::BUTTON2_DOUBLE_CLICKED | | ncurses::BUTTON2_DOUBLE_CLICKED
ncurses::BUTTON3_DOUBLE_CLICKED | | ncurses::BUTTON3_DOUBLE_CLICKED
ncurses::BUTTON4_DOUBLE_CLICKED | | ncurses::BUTTON4_DOUBLE_CLICKED
ncurses::BUTTON5_DOUBLE_CLICKED => for _ in 0..2 { | ncurses::BUTTON5_DOUBLE_CLICKED => for _ in 0..2 {
f(MouseEvent::Press(button)); f(MouseEvent::Press(button));
f(MouseEvent::Release(button)); f(MouseEvent::Release(button));
}, },
ncurses::BUTTON1_TRIPLE_CLICKED | ncurses::BUTTON1_TRIPLE_CLICKED
ncurses::BUTTON2_TRIPLE_CLICKED | | ncurses::BUTTON2_TRIPLE_CLICKED
ncurses::BUTTON3_TRIPLE_CLICKED | | ncurses::BUTTON3_TRIPLE_CLICKED
ncurses::BUTTON4_TRIPLE_CLICKED | | ncurses::BUTTON4_TRIPLE_CLICKED
ncurses::BUTTON5_TRIPLE_CLICKED => for _ in 0..3 { | ncurses::BUTTON5_TRIPLE_CLICKED => for _ in 0..3 {
f(MouseEvent::Press(button)); f(MouseEvent::Press(button));
f(MouseEvent::Release(button)); f(MouseEvent::Release(button));
}, },

View File

@ -73,27 +73,20 @@ impl Concrete {
Ok(event) => event, Ok(event) => event,
}; };
let _shift = let _shift = (mevent.bstate & pancurses::BUTTON_SHIFT as mmask_t) != 0;
(mevent.bstate & pancurses::BUTTON_SHIFT as mmask_t) != 0; let _alt = (mevent.bstate & pancurses::BUTTON_ALT as mmask_t) != 0;
let _alt = let _ctrl = (mevent.bstate & pancurses::BUTTON_CTRL as mmask_t) != 0;
(mevent.bstate & pancurses::BUTTON_ALT as mmask_t) != 0;
let _ctrl =
(mevent.bstate & pancurses::BUTTON_CTRL as mmask_t) != 0;
mevent.bstate &= !(pancurses::BUTTON_SHIFT | pancurses::BUTTON_ALT mevent.bstate &= !(pancurses::BUTTON_SHIFT | pancurses::BUTTON_ALT
| pancurses::BUTTON_CTRL) | pancurses::BUTTON_CTRL) as mmask_t;
as mmask_t;
let make_event = |event| { let make_event = |event| Event::Mouse {
Event::Mouse { offset: Vec2::zero(),
offset: Vec2::zero(), position: Vec2::new(mevent.x as usize, mevent.y as usize),
position: Vec2::new(mevent.x as usize, mevent.y as usize), event: event,
event: event,
}
}; };
if mevent.bstate == pancurses::REPORT_MOUSE_POSITION as mmask_t if mevent.bstate == pancurses::REPORT_MOUSE_POSITION as mmask_t {
{
// The event is either a mouse drag event, // The event is either a mouse drag event,
// or a weird double-release event. :S // or a weird double-release event. :S
self.last_mouse_button self.last_mouse_button
@ -221,206 +214,216 @@ impl backend::Backend for Concrete {
fn poll_event(&mut self) -> Event { fn poll_event(&mut self) -> Event {
self.event_queue.pop().unwrap_or_else(|| { self.event_queue.pop().unwrap_or_else(|| {
if let Some(ev) = self.window.getch() { if let Some(ev) = self.window.getch() {
match ev { match ev {
pancurses::Input::Character('\n') => Event::Key(Key::Enter), pancurses::Input::Character('\n') => {
// TODO: wait for a very short delay. If more keys are Event::Key(Key::Enter)
// pipelined, it may be an escape sequence.
pancurses::Input::Character('\u{7f}') |
pancurses::Input::Character('\u{8}') => {
Event::Key(Key::Backspace)
}
pancurses::Input::Character('\u{9}') => Event::Key(Key::Tab),
pancurses::Input::Character('\u{1b}') => Event::Key(Key::Esc),
pancurses::Input::Character(c)
if 32 <= (c as u32) && (c as u32) <= 255 =>
{
Event::Char(
utf8::read_char(c as u8, || {
self.window.getch().and_then(|i| match i {
pancurses::Input::Character(c) => {
Some(c as u8)
}
_ => None,
})
}).unwrap(),
)
}
pancurses::Input::Character(c) if (c as u32) <= 26 => {
Event::CtrlChar((b'a' - 1 + c as u8) as char)
}
pancurses::Input::Character(c) => {
let mut bytes = [0u8; 4];
Event::Unknown(
c.encode_utf8(&mut bytes).as_bytes().to_vec(),
)
}
// TODO: Some key combos are not recognized by pancurses,
// but are sent as Unknown. We could still parse them here.
pancurses::Input::Unknown(code) => match code {
220 => Event::Ctrl(Key::Del),
224 => Event::Alt(Key::Down),
225 => Event::AltShift(Key::Down),
226 => Event::Ctrl(Key::Down),
227 => Event::CtrlShift(Key::Down),
229 => Event::Alt(Key::End),
230 => Event::AltShift(Key::End),
231 => Event::Ctrl(Key::End),
232 => Event::CtrlShift(Key::End),
235 => Event::Alt(Key::Home),
236 => Event::AltShift(Key::Home),
237 => Event::Ctrl(Key::Home),
238 => Event::CtrlShift(Key::Home),
246 => Event::Alt(Key::Left),
247 => Event::AltShift(Key::Left),
248 => Event::Ctrl(Key::Left),
249 => Event::CtrlShift(Key::Left),
251 => Event::Alt(Key::PageDown),
252 => Event::AltShift(Key::PageDown),
253 => Event::Ctrl(Key::PageDown),
254 => Event::CtrlShift(Key::PageDown),
256 => Event::Alt(Key::PageUp),
257 => Event::AltShift(Key::PageUp),
258 => Event::Ctrl(Key::PageUp),
259 => Event::CtrlShift(Key::PageUp),
261 => Event::Alt(Key::Right),
262 => Event::AltShift(Key::Right),
263 => Event::Ctrl(Key::Right),
264 => Event::CtrlShift(Key::Right),
267 => Event::Alt(Key::Up),
268 => Event::AltShift(Key::Up),
269 => Event::Ctrl(Key::Up),
270 => Event::CtrlShift(Key::Up),
other => {
warn!("Unknown: {}", other);
Event::Unknown(split_i32(other))
} }
}, // TODO: wait for a very short delay. If more keys are
// TODO: I honestly have no fucking idea what KeyCodeYes is // pipelined, it may be an escape sequence.
pancurses::Input::KeyCodeYes => Event::Refresh, pancurses::Input::Character('\u{7f}')
pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak), | pancurses::Input::Character('\u{8}') => {
pancurses::Input::KeyDown => Event::Key(Key::Down), Event::Key(Key::Backspace)
pancurses::Input::KeyUp => Event::Key(Key::Up), }
pancurses::Input::KeyLeft => Event::Key(Key::Left), pancurses::Input::Character('\u{9}') => {
pancurses::Input::KeyRight => Event::Key(Key::Right), Event::Key(Key::Tab)
pancurses::Input::KeyHome => Event::Key(Key::Home), }
pancurses::Input::KeyBackspace => Event::Key(Key::Backspace), pancurses::Input::Character('\u{1b}') => {
pancurses::Input::KeyF0 => Event::Key(Key::F0), Event::Key(Key::Esc)
pancurses::Input::KeyF1 => Event::Key(Key::F1), }
pancurses::Input::KeyF2 => Event::Key(Key::F2), pancurses::Input::Character(c)
pancurses::Input::KeyF3 => Event::Key(Key::F3), if 32 <= (c as u32) && (c as u32) <= 255 =>
pancurses::Input::KeyF4 => Event::Key(Key::F4), {
pancurses::Input::KeyF5 => Event::Key(Key::F5), Event::Char(
pancurses::Input::KeyF6 => Event::Key(Key::F6), utf8::read_char(c as u8, || {
pancurses::Input::KeyF7 => Event::Key(Key::F7), self.window.getch().and_then(|i| match i {
pancurses::Input::KeyF8 => Event::Key(Key::F8), pancurses::Input::Character(c) => {
pancurses::Input::KeyF9 => Event::Key(Key::F9), Some(c as u8)
pancurses::Input::KeyF10 => Event::Key(Key::F10), }
pancurses::Input::KeyF11 => Event::Key(Key::F11), _ => None,
pancurses::Input::KeyF12 => Event::Key(Key::F12), })
pancurses::Input::KeyF13 => Event::Shift(Key::F1), }).unwrap(),
pancurses::Input::KeyF14 => Event::Shift(Key::F2), )
pancurses::Input::KeyF15 => Event::Shift(Key::F3), }
pancurses::Input::KeyDL => Event::Refresh, pancurses::Input::Character(c) if (c as u32) <= 26 => {
pancurses::Input::KeyIL => Event::Refresh, Event::CtrlChar((b'a' - 1 + c as u8) as char)
pancurses::Input::KeyDC => Event::Key(Key::Del), }
pancurses::Input::KeyIC => Event::Key(Key::Ins), pancurses::Input::Character(c) => {
pancurses::Input::KeyEIC => Event::Refresh, let mut bytes = [0u8; 4];
pancurses::Input::KeyClear => Event::Refresh, Event::Unknown(
pancurses::Input::KeyEOS => Event::Refresh, c.encode_utf8(&mut bytes).as_bytes().to_vec(),
pancurses::Input::KeyEOL => Event::Refresh, )
pancurses::Input::KeySF => Event::Shift(Key::Down), }
pancurses::Input::KeySR => Event::Shift(Key::Up), // TODO: Some key combos are not recognized by pancurses,
pancurses::Input::KeyNPage => Event::Key(Key::PageDown), // but are sent as Unknown. We could still parse them here.
pancurses::Input::KeyPPage => Event::Key(Key::PageUp), pancurses::Input::Unknown(code) => match code {
pancurses::Input::KeySTab => Event::Shift(Key::Tab), 220 => Event::Ctrl(Key::Del),
pancurses::Input::KeyCTab => Event::Ctrl(Key::Tab),
pancurses::Input::KeyCATab => Event::CtrlAlt(Key::Tab), 224 => Event::Alt(Key::Down),
pancurses::Input::KeyEnter => Event::Key(Key::Enter), 225 => Event::AltShift(Key::Down),
pancurses::Input::KeySReset => Event::Refresh, 226 => Event::Ctrl(Key::Down),
pancurses::Input::KeyReset => Event::Refresh, 227 => Event::CtrlShift(Key::Down),
pancurses::Input::KeyPrint => Event::Refresh,
pancurses::Input::KeyLL => Event::Refresh, 229 => Event::Alt(Key::End),
pancurses::Input::KeyAbort => Event::Refresh, 230 => Event::AltShift(Key::End),
pancurses::Input::KeySHelp => Event::Refresh, 231 => Event::Ctrl(Key::End),
pancurses::Input::KeyLHelp => Event::Refresh, 232 => Event::CtrlShift(Key::End),
pancurses::Input::KeyBTab => Event::Shift(Key::Tab),
pancurses::Input::KeyBeg => Event::Refresh, 235 => Event::Alt(Key::Home),
pancurses::Input::KeyCancel => Event::Refresh, 236 => Event::AltShift(Key::Home),
pancurses::Input::KeyClose => Event::Refresh, 237 => Event::Ctrl(Key::Home),
pancurses::Input::KeyCommand => Event::Refresh, 238 => Event::CtrlShift(Key::Home),
pancurses::Input::KeyCopy => Event::Refresh,
pancurses::Input::KeyCreate => Event::Refresh, 246 => Event::Alt(Key::Left),
pancurses::Input::KeyEnd => Event::Key(Key::End), 247 => Event::AltShift(Key::Left),
pancurses::Input::KeyExit => Event::Refresh, 248 => Event::Ctrl(Key::Left),
pancurses::Input::KeyFind => Event::Refresh, 249 => Event::CtrlShift(Key::Left),
pancurses::Input::KeyHelp => Event::Refresh,
pancurses::Input::KeyMark => Event::Refresh, 251 => Event::Alt(Key::PageDown),
pancurses::Input::KeyMessage => Event::Refresh, 252 => Event::AltShift(Key::PageDown),
pancurses::Input::KeyMove => Event::Refresh, 253 => Event::Ctrl(Key::PageDown),
pancurses::Input::KeyNext => Event::Refresh, 254 => Event::CtrlShift(Key::PageDown),
pancurses::Input::KeyOpen => Event::Refresh,
pancurses::Input::KeyOptions => Event::Refresh, 256 => Event::Alt(Key::PageUp),
pancurses::Input::KeyPrevious => Event::Refresh, 257 => Event::AltShift(Key::PageUp),
pancurses::Input::KeyRedo => Event::Refresh, 258 => Event::Ctrl(Key::PageUp),
pancurses::Input::KeyReference => Event::Refresh, 259 => Event::CtrlShift(Key::PageUp),
pancurses::Input::KeyRefresh => Event::Refresh,
pancurses::Input::KeyReplace => Event::Refresh, 261 => Event::Alt(Key::Right),
pancurses::Input::KeyRestart => Event::Refresh, 262 => Event::AltShift(Key::Right),
pancurses::Input::KeyResume => Event::Refresh, 263 => Event::Ctrl(Key::Right),
pancurses::Input::KeySave => Event::Refresh, 264 => Event::CtrlShift(Key::Right),
pancurses::Input::KeySBeg => Event::Refresh,
pancurses::Input::KeySCancel => Event::Refresh, 267 => Event::Alt(Key::Up),
pancurses::Input::KeySCommand => Event::Refresh, 268 => Event::AltShift(Key::Up),
pancurses::Input::KeySCopy => Event::Refresh, 269 => Event::Ctrl(Key::Up),
pancurses::Input::KeySCreate => Event::Refresh, 270 => Event::CtrlShift(Key::Up),
pancurses::Input::KeySDC => Event::Shift(Key::Del), other => {
pancurses::Input::KeySDL => Event::Refresh, warn!("Unknown: {}", other);
pancurses::Input::KeySelect => Event::Refresh, Event::Unknown(split_i32(other))
pancurses::Input::KeySEnd => Event::Shift(Key::End), }
pancurses::Input::KeySEOL => Event::Refresh, },
pancurses::Input::KeySExit => Event::Refresh, // TODO: I honestly have no fucking idea what KeyCodeYes is
pancurses::Input::KeySFind => Event::Refresh, pancurses::Input::KeyCodeYes => Event::Refresh,
pancurses::Input::KeySHome => Event::Shift(Key::Home), pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
pancurses::Input::KeySIC => Event::Shift(Key::Ins), pancurses::Input::KeyDown => Event::Key(Key::Down),
pancurses::Input::KeySLeft => Event::Shift(Key::Left), pancurses::Input::KeyUp => Event::Key(Key::Up),
pancurses::Input::KeySMessage => Event::Refresh, pancurses::Input::KeyLeft => Event::Key(Key::Left),
pancurses::Input::KeySMove => Event::Refresh, pancurses::Input::KeyRight => Event::Key(Key::Right),
pancurses::Input::KeySNext => Event::Shift(Key::PageDown), pancurses::Input::KeyHome => Event::Key(Key::Home),
pancurses::Input::KeySOptions => Event::Refresh, pancurses::Input::KeyBackspace => {
pancurses::Input::KeySPrevious => Event::Shift(Key::PageUp), Event::Key(Key::Backspace)
pancurses::Input::KeySPrint => Event::Refresh, }
pancurses::Input::KeySRedo => Event::Refresh, pancurses::Input::KeyF0 => Event::Key(Key::F0),
pancurses::Input::KeySReplace => Event::Refresh, pancurses::Input::KeyF1 => Event::Key(Key::F1),
pancurses::Input::KeySRight => Event::Shift(Key::Right), pancurses::Input::KeyF2 => Event::Key(Key::F2),
pancurses::Input::KeySResume => Event::Refresh, pancurses::Input::KeyF3 => Event::Key(Key::F3),
pancurses::Input::KeySSave => Event::Refresh, pancurses::Input::KeyF4 => Event::Key(Key::F4),
pancurses::Input::KeySSuspend => Event::Refresh, pancurses::Input::KeyF5 => Event::Key(Key::F5),
pancurses::Input::KeySUndo => Event::Refresh, pancurses::Input::KeyF6 => Event::Key(Key::F6),
pancurses::Input::KeySuspend => Event::Refresh, pancurses::Input::KeyF7 => Event::Key(Key::F7),
pancurses::Input::KeyUndo => Event::Refresh, pancurses::Input::KeyF8 => Event::Key(Key::F8),
pancurses::Input::KeyResize => Event::WindowResize, pancurses::Input::KeyF9 => Event::Key(Key::F9),
pancurses::Input::KeyEvent => Event::Refresh, pancurses::Input::KeyF10 => Event::Key(Key::F10),
// TODO: mouse support pancurses::Input::KeyF11 => Event::Key(Key::F11),
pancurses::Input::KeyMouse => self.parse_mouse_event(), pancurses::Input::KeyF12 => Event::Key(Key::F12),
pancurses::Input::KeyA1 => Event::Refresh, pancurses::Input::KeyF13 => Event::Shift(Key::F1),
pancurses::Input::KeyA3 => Event::Refresh, pancurses::Input::KeyF14 => Event::Shift(Key::F2),
pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter), pancurses::Input::KeyF15 => Event::Shift(Key::F3),
pancurses::Input::KeyC1 => Event::Refresh, pancurses::Input::KeyDL => Event::Refresh,
pancurses::Input::KeyC3 => Event::Refresh, pancurses::Input::KeyIL => Event::Refresh,
pancurses::Input::KeyDC => Event::Key(Key::Del),
pancurses::Input::KeyIC => Event::Key(Key::Ins),
pancurses::Input::KeyEIC => Event::Refresh,
pancurses::Input::KeyClear => Event::Refresh,
pancurses::Input::KeyEOS => Event::Refresh,
pancurses::Input::KeyEOL => Event::Refresh,
pancurses::Input::KeySF => Event::Shift(Key::Down),
pancurses::Input::KeySR => Event::Shift(Key::Up),
pancurses::Input::KeyNPage => Event::Key(Key::PageDown),
pancurses::Input::KeyPPage => Event::Key(Key::PageUp),
pancurses::Input::KeySTab => Event::Shift(Key::Tab),
pancurses::Input::KeyCTab => Event::Ctrl(Key::Tab),
pancurses::Input::KeyCATab => Event::CtrlAlt(Key::Tab),
pancurses::Input::KeyEnter => Event::Key(Key::Enter),
pancurses::Input::KeySReset => Event::Refresh,
pancurses::Input::KeyReset => Event::Refresh,
pancurses::Input::KeyPrint => Event::Refresh,
pancurses::Input::KeyLL => Event::Refresh,
pancurses::Input::KeyAbort => Event::Refresh,
pancurses::Input::KeySHelp => Event::Refresh,
pancurses::Input::KeyLHelp => Event::Refresh,
pancurses::Input::KeyBTab => Event::Shift(Key::Tab),
pancurses::Input::KeyBeg => Event::Refresh,
pancurses::Input::KeyCancel => Event::Refresh,
pancurses::Input::KeyClose => Event::Refresh,
pancurses::Input::KeyCommand => Event::Refresh,
pancurses::Input::KeyCopy => Event::Refresh,
pancurses::Input::KeyCreate => Event::Refresh,
pancurses::Input::KeyEnd => Event::Key(Key::End),
pancurses::Input::KeyExit => Event::Refresh,
pancurses::Input::KeyFind => Event::Refresh,
pancurses::Input::KeyHelp => Event::Refresh,
pancurses::Input::KeyMark => Event::Refresh,
pancurses::Input::KeyMessage => Event::Refresh,
pancurses::Input::KeyMove => Event::Refresh,
pancurses::Input::KeyNext => Event::Refresh,
pancurses::Input::KeyOpen => Event::Refresh,
pancurses::Input::KeyOptions => Event::Refresh,
pancurses::Input::KeyPrevious => Event::Refresh,
pancurses::Input::KeyRedo => Event::Refresh,
pancurses::Input::KeyReference => Event::Refresh,
pancurses::Input::KeyRefresh => Event::Refresh,
pancurses::Input::KeyReplace => Event::Refresh,
pancurses::Input::KeyRestart => Event::Refresh,
pancurses::Input::KeyResume => Event::Refresh,
pancurses::Input::KeySave => Event::Refresh,
pancurses::Input::KeySBeg => Event::Refresh,
pancurses::Input::KeySCancel => Event::Refresh,
pancurses::Input::KeySCommand => Event::Refresh,
pancurses::Input::KeySCopy => Event::Refresh,
pancurses::Input::KeySCreate => Event::Refresh,
pancurses::Input::KeySDC => Event::Shift(Key::Del),
pancurses::Input::KeySDL => Event::Refresh,
pancurses::Input::KeySelect => Event::Refresh,
pancurses::Input::KeySEnd => Event::Shift(Key::End),
pancurses::Input::KeySEOL => Event::Refresh,
pancurses::Input::KeySExit => Event::Refresh,
pancurses::Input::KeySFind => Event::Refresh,
pancurses::Input::KeySHome => Event::Shift(Key::Home),
pancurses::Input::KeySIC => Event::Shift(Key::Ins),
pancurses::Input::KeySLeft => Event::Shift(Key::Left),
pancurses::Input::KeySMessage => Event::Refresh,
pancurses::Input::KeySMove => Event::Refresh,
pancurses::Input::KeySNext => Event::Shift(Key::PageDown),
pancurses::Input::KeySOptions => Event::Refresh,
pancurses::Input::KeySPrevious => {
Event::Shift(Key::PageUp)
}
pancurses::Input::KeySPrint => Event::Refresh,
pancurses::Input::KeySRedo => Event::Refresh,
pancurses::Input::KeySReplace => Event::Refresh,
pancurses::Input::KeySRight => Event::Shift(Key::Right),
pancurses::Input::KeySResume => Event::Refresh,
pancurses::Input::KeySSave => Event::Refresh,
pancurses::Input::KeySSuspend => Event::Refresh,
pancurses::Input::KeySUndo => Event::Refresh,
pancurses::Input::KeySuspend => Event::Refresh,
pancurses::Input::KeyUndo => Event::Refresh,
pancurses::Input::KeyResize => Event::WindowResize,
pancurses::Input::KeyEvent => Event::Refresh,
// TODO: mouse support
pancurses::Input::KeyMouse => self.parse_mouse_event(),
pancurses::Input::KeyA1 => Event::Refresh,
pancurses::Input::KeyA3 => Event::Refresh,
pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
pancurses::Input::KeyC1 => Event::Refresh,
pancurses::Input::KeyC3 => Event::Refresh,
}
} else {
Event::Refresh
} }
} else { })
Event::Refresh
}
})
} }
fn set_refresh_rate(&mut self, fps: u32) { fn set_refresh_rate(&mut self, fps: u32) {
@ -447,36 +450,36 @@ where
match bare_event { match bare_event {
pancurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp), pancurses::BUTTON4_PRESSED => f(MouseEvent::WheelUp),
pancurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown), pancurses::BUTTON5_PRESSED => f(MouseEvent::WheelDown),
pancurses::BUTTON1_RELEASED | pancurses::BUTTON1_RELEASED
pancurses::BUTTON2_RELEASED | | pancurses::BUTTON2_RELEASED
pancurses::BUTTON3_RELEASED | | pancurses::BUTTON3_RELEASED
pancurses::BUTTON4_RELEASED | | pancurses::BUTTON4_RELEASED
pancurses::BUTTON5_RELEASED => f(MouseEvent::Release(button)), | pancurses::BUTTON5_RELEASED => f(MouseEvent::Release(button)),
pancurses::BUTTON1_PRESSED | pancurses::BUTTON1_PRESSED
pancurses::BUTTON2_PRESSED | | pancurses::BUTTON2_PRESSED
pancurses::BUTTON3_PRESSED => f(MouseEvent::Press(button)), | pancurses::BUTTON3_PRESSED => f(MouseEvent::Press(button)),
pancurses::BUTTON1_CLICKED | pancurses::BUTTON1_CLICKED
pancurses::BUTTON2_CLICKED | | pancurses::BUTTON2_CLICKED
pancurses::BUTTON3_CLICKED | | pancurses::BUTTON3_CLICKED
pancurses::BUTTON4_CLICKED | | pancurses::BUTTON4_CLICKED
pancurses::BUTTON5_CLICKED => { | pancurses::BUTTON5_CLICKED => {
f(MouseEvent::Press(button)); f(MouseEvent::Press(button));
f(MouseEvent::Release(button)); f(MouseEvent::Release(button));
} }
// Well, we disabled click detection // Well, we disabled click detection
pancurses::BUTTON1_DOUBLE_CLICKED | pancurses::BUTTON1_DOUBLE_CLICKED
pancurses::BUTTON2_DOUBLE_CLICKED | | pancurses::BUTTON2_DOUBLE_CLICKED
pancurses::BUTTON3_DOUBLE_CLICKED | | pancurses::BUTTON3_DOUBLE_CLICKED
pancurses::BUTTON4_DOUBLE_CLICKED | | pancurses::BUTTON4_DOUBLE_CLICKED
pancurses::BUTTON5_DOUBLE_CLICKED => for _ in 0..2 { | pancurses::BUTTON5_DOUBLE_CLICKED => for _ in 0..2 {
f(MouseEvent::Press(button)); f(MouseEvent::Press(button));
f(MouseEvent::Release(button)); f(MouseEvent::Release(button));
}, },
pancurses::BUTTON1_TRIPLE_CLICKED | pancurses::BUTTON1_TRIPLE_CLICKED
pancurses::BUTTON2_TRIPLE_CLICKED | | pancurses::BUTTON2_TRIPLE_CLICKED
pancurses::BUTTON3_TRIPLE_CLICKED | | pancurses::BUTTON3_TRIPLE_CLICKED
pancurses::BUTTON4_TRIPLE_CLICKED | | pancurses::BUTTON4_TRIPLE_CLICKED
pancurses::BUTTON5_TRIPLE_CLICKED => for _ in 0..3 { | pancurses::BUTTON5_TRIPLE_CLICKED => for _ in 0..3 {
f(MouseEvent::Press(button)); f(MouseEvent::Press(button));
f(MouseEvent::Release(button)); f(MouseEvent::Release(button));
}, },
@ -487,32 +490,31 @@ where
/// Returns the Key enum corresponding to the given pancurses event. /// Returns the Key enum corresponding to the given pancurses event.
fn get_mouse_button(bare_event: mmask_t) -> MouseButton { fn get_mouse_button(bare_event: mmask_t) -> MouseButton {
match bare_event { match bare_event {
pancurses::BUTTON1_RELEASED | pancurses::BUTTON1_RELEASED
pancurses::BUTTON1_PRESSED | | pancurses::BUTTON1_PRESSED
pancurses::BUTTON1_CLICKED | | pancurses::BUTTON1_CLICKED
pancurses::BUTTON1_DOUBLE_CLICKED | | pancurses::BUTTON1_DOUBLE_CLICKED
pancurses::BUTTON1_TRIPLE_CLICKED => MouseButton::Left, | pancurses::BUTTON1_TRIPLE_CLICKED => MouseButton::Left,
pancurses::BUTTON2_RELEASED | pancurses::BUTTON2_RELEASED
pancurses::BUTTON2_PRESSED | | pancurses::BUTTON2_PRESSED
pancurses::BUTTON2_CLICKED | | pancurses::BUTTON2_CLICKED
pancurses::BUTTON2_DOUBLE_CLICKED | | pancurses::BUTTON2_DOUBLE_CLICKED
pancurses::BUTTON2_TRIPLE_CLICKED => MouseButton::Middle, | pancurses::BUTTON2_TRIPLE_CLICKED => MouseButton::Middle,
pancurses::BUTTON3_RELEASED | pancurses::BUTTON3_RELEASED
pancurses::BUTTON3_PRESSED | | pancurses::BUTTON3_PRESSED
pancurses::BUTTON3_CLICKED | | pancurses::BUTTON3_CLICKED
pancurses::BUTTON3_DOUBLE_CLICKED | | pancurses::BUTTON3_DOUBLE_CLICKED
pancurses::BUTTON3_TRIPLE_CLICKED => MouseButton::Right, | pancurses::BUTTON3_TRIPLE_CLICKED => MouseButton::Right,
pancurses::BUTTON4_RELEASED | pancurses::BUTTON4_RELEASED
pancurses::BUTTON4_PRESSED | | pancurses::BUTTON4_PRESSED
pancurses::BUTTON4_CLICKED | | pancurses::BUTTON4_CLICKED
pancurses::BUTTON4_DOUBLE_CLICKED | | pancurses::BUTTON4_DOUBLE_CLICKED
pancurses::BUTTON4_TRIPLE_CLICKED => MouseButton::Button4, | pancurses::BUTTON4_TRIPLE_CLICKED => MouseButton::Button4,
pancurses::BUTTON5_RELEASED | pancurses::BUTTON5_RELEASED
pancurses::BUTTON5_PRESSED | | pancurses::BUTTON5_PRESSED
pancurses::BUTTON5_CLICKED | | pancurses::BUTTON5_CLICKED
pancurses::BUTTON5_DOUBLE_CLICKED | | pancurses::BUTTON5_DOUBLE_CLICKED
pancurses::BUTTON5_TRIPLE_CLICKED => MouseButton::Button5, | pancurses::BUTTON5_TRIPLE_CLICKED => MouseButton::Button5,
_ => MouseButton::Other, _ => MouseButton::Other,
} }
} }

View File

@ -143,9 +143,11 @@ impl backend::Backend for Concrete {
let (sender, receiver) = chan::async(); let (sender, receiver) = chan::async();
thread::spawn(move || for key in ::std::io::stdin().events() { thread::spawn(move || {
if let Ok(key) = key { for key in ::std::io::stdin().events() {
sender.send(key) if let Ok(key) = key {
sender.send(key)
}
} }
}); });

View File

@ -464,7 +464,6 @@ impl Cursive {
self.running self.running
} }
/// Runs the event loop. /// Runs the event loop.
/// ///
/// It will wait for user input (key presses) /// It will wait for user input (key presses)

View File

@ -198,10 +198,10 @@ impl Absolute {
/// orientation (ex: `Left` and `Vertical`). /// orientation (ex: `Left` and `Vertical`).
pub fn relative(self, orientation: Orientation) -> Option<Relative> { pub fn relative(self, orientation: Orientation) -> Option<Relative> {
match (orientation, self) { match (orientation, self) {
(Orientation::Horizontal, Absolute::Left) | (Orientation::Horizontal, Absolute::Left)
(Orientation::Vertical, Absolute::Up) => Some(Relative::Front), | (Orientation::Vertical, Absolute::Up) => Some(Relative::Front),
(Orientation::Horizontal, Absolute::Right) | (Orientation::Horizontal, Absolute::Right)
(Orientation::Vertical, Absolute::Down) => Some(Relative::Back), | (Orientation::Vertical, Absolute::Down) => Some(Relative::Back),
_ => None, _ => None,
} }
} }

View File

@ -13,7 +13,6 @@
//! [global callback](../struct.Cursive.html#method.add_global_callback) //! [global callback](../struct.Cursive.html#method.add_global_callback)
//! table is checked. //! table is checked.
use Cursive; use Cursive;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;

View File

@ -59,10 +59,10 @@
//! Or you can use gdb as usual. //! Or you can use gdb as usual.
#![deny(missing_docs)] #![deny(missing_docs)]
#[macro_use]
extern crate maplit;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[macro_use]
extern crate maplit;
extern crate num; extern crate num;
extern crate owning_ref; extern crate owning_ref;
extern crate toml; extern crate toml;
@ -109,7 +109,6 @@ mod utf8;
#[doc(hidden)] #[doc(hidden)]
pub mod backend; pub mod backend;
pub use cursive::{Cursive, ScreenId}; pub use cursive::{Cursive, ScreenId};
pub use printer::Printer; pub use printer::Printer;
pub use with::With; pub use with::With;

View File

@ -113,7 +113,6 @@ impl MenuTree {
.insert(i, MenuItem::Leaf(title, Callback::from_fn(cb))); .insert(i, MenuItem::Leaf(title, Callback::from_fn(cb)));
} }
/// Adds a actionnable leaf to the end of this tree - chainable variant. /// Adds a actionnable leaf to the end of this tree - chainable variant.
pub fn leaf<S, F>(self, title: S, cb: F) -> Self pub fn leaf<S, F>(self, title: S, cb: F) -> Self
where where
@ -173,13 +172,13 @@ impl MenuTree {
/// Returns `None` if the given title was not found, /// Returns `None` if the given title was not found,
/// or if it wasn't a subtree. /// or if it wasn't a subtree.
pub fn find_subtree(&mut self, title: &str) -> Option<&mut MenuTree> { pub fn find_subtree(&mut self, title: &str) -> Option<&mut MenuTree> {
self.find_item(title).and_then( self.find_item(title).and_then(|item| {
|item| if let MenuItem::Subtree(_, ref mut tree) = *item { if let MenuItem::Subtree(_, ref mut tree) = *item {
Some(Rc::make_mut(tree)) Some(Rc::make_mut(tree))
} else { } else {
None None
}, }
) })
} }
/// Removes the item at the given position. /// Removes the item at the given position.

View File

@ -1,6 +1,5 @@
//! Makes drawing on ncurses windows easier. //! Makes drawing on ncurses windows easier.
use backend::{self, Backend}; use backend::{self, Backend};
use std::cell::Cell; use std::cell::Cell;
use std::cmp::min; use std::cmp::min;

View File

@ -517,9 +517,11 @@ impl Color {
let rgb: Vec<_> = let rgb: Vec<_> =
value.chars().map(|c| c as i16 - '0' as i16).collect(); value.chars().map(|c| c as i16 - '0' as i16).collect();
if rgb.iter().all(|&i| i >= 0 && i < 6) { if rgb.iter().all(|&i| i >= 0 && i < 6) {
Some( Some(Color::RgbLowRes(
Color::RgbLowRes(rgb[0] as u8, rgb[1] as u8, rgb[2] as u8), rgb[0] as u8,
) rgb[1] as u8,
rgb[2] as u8,
))
} else { } else {
None None
} }

View File

@ -1,5 +1,3 @@
use With; use With;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;

View File

@ -10,7 +10,6 @@ pub struct ProgressReader<R: Read> {
counter: Counter, counter: Counter,
} }
impl<R: Read> ProgressReader<R> { impl<R: Read> ProgressReader<R> {
/// Creates a new `ProgressReader` around `reader`. /// Creates a new `ProgressReader` around `reader`.
/// ///

View File

@ -320,7 +320,6 @@ impl<T: Into<Vec4>> Sub<T> for Vec4 {
} }
} }
impl Div<usize> for Vec4 { impl Div<usize> for Vec4 {
type Output = Vec4; type Output = Vec4;

View File

@ -49,7 +49,6 @@ mod scroll;
mod identifiable; mod identifiable;
mod boxable; mod boxable;
pub use self::boxable::Boxable; pub use self::boxable::Boxable;
pub use self::identifiable::Identifiable; pub use self::identifiable::Identifiable;
pub use self::position::{Offset, Position}; pub use self::position::{Offset, Position};
@ -182,14 +181,15 @@ impl<T: View> Finder for T {
let result_ref = &mut result; let result_ref = &mut result;
let mut callback = Some(callback); let mut callback = Some(callback);
let callback = |v: &mut Any| if let Some(callback) = let callback = |v: &mut Any| {
callback.take() if let Some(callback) = callback.take() {
{ if v.is::<V>() {
if v.is::<V>() { *result_ref =
*result_ref = v.downcast_mut::<V>().map(|v| callback(v)); v.downcast_mut::<V>().map(|v| callback(v));
} else if v.is::<IdView<V>>() { } else if v.is::<IdView<V>>() {
*result_ref = v.downcast_mut::<IdView<V>>() *result_ref = v.downcast_mut::<IdView<V>>()
.and_then(|v| v.with_view_mut(callback)); .and_then(|v| v.with_view_mut(callback));
}
} }
}; };
self.call_on_any(sel, Box::new(callback)); self.call_on_any(sel, Box::new(callback));

View File

@ -178,7 +178,6 @@ impl ScrollBase {
return false; return false;
} }
// Now, did we hit the thumb? Or should we direct-jump? // Now, did we hit the thumb? Or should we direct-jump?
let height = self.scrollbar_thumb_height(); let height = self.scrollbar_thumb_height();
let thumb_y = self.scrollbar_thumb_y(height); let thumb_y = self.scrollbar_thumb_y(height);
@ -218,7 +217,6 @@ impl ScrollBase {
self.thumb_grab = None; self.thumb_grab = None;
} }
/// Draws the scroll bar and the content using the given drawer. /// Draws the scroll bar and the content using the given drawer.
/// ///
/// `line_drawer` will be called once for each line that needs to be drawn. /// `line_drawer` will be called once for each line that needs to be drawn.
@ -269,7 +267,6 @@ impl ScrollBase {
); );
} }
// And draw the scrollbar if needed // And draw the scrollbar if needed
if self.view_height < self.content_height { if self.view_height < self.content_height {
// We directly compute the size of the scrollbar // We directly compute the size of the scrollbar

View File

@ -25,9 +25,9 @@ impl SizeConstraint {
/// When `available` is offered to the `BoxView`. /// When `available` is offered to the `BoxView`.
pub fn available(self, available: usize) -> usize { pub fn available(self, available: usize) -> usize {
match self { match self {
SizeConstraint::Free | SizeConstraint::Free
SizeConstraint::Full | | SizeConstraint::Full
SizeConstraint::AtLeast(_) => available, | SizeConstraint::AtLeast(_) => available,
// If the available space is too small, always give in. // If the available space is too small, always give in.
SizeConstraint::Fixed(value) | SizeConstraint::AtMost(value) => { SizeConstraint::Fixed(value) | SizeConstraint::AtMost(value) => {
min(value, available) min(value, available)

View File

@ -34,7 +34,6 @@ pub trait ViewWrapper: 'static {
where where
F: FnOnce(&mut Self::V) -> R; F: FnOnce(&mut Self::V) -> R;
/// Attempts to retrieve the inner view. /// Attempts to retrieve the inner view.
fn into_inner(self) -> Result<Self::V, Self> fn into_inner(self) -> Result<Self::V, Self>
where where
@ -74,9 +73,7 @@ pub trait ViewWrapper: 'static {
/// Wraps the `find` method. /// Wraps the `find` method.
fn wrap_call_on_any<'a>( fn wrap_call_on_any<'a>(
&mut self, &mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a>
selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>,
) { ) {
self.with_view_mut(|v| v.call_on_any(selector, callback)); self.with_view_mut(|v| v.call_on_any(selector, callback));
} }
@ -96,7 +93,8 @@ pub trait ViewWrapper: 'static {
// Some types easily implement ViewWrapper. // Some types easily implement ViewWrapper.
// This includes Box<T: View> // This includes Box<T: View>
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
impl<U: View + ?Sized, T: Deref<Target = U> + DerefMut + 'static> ViewWrapper for T { impl<U: View + ?Sized, T: Deref<Target = U> + DerefMut + 'static> ViewWrapper
for T {
type V = U; type V = U;
fn with_view<F, R>(&self, f: F) -> Option<R> fn with_view<F, R>(&self, f: F) -> Option<R>
@ -137,9 +135,7 @@ impl<T: ViewWrapper> View for T {
} }
fn call_on_any<'a>( fn call_on_any<'a>(
&mut self, &mut self, selector: &Selector, callback: Box<FnMut(&mut Any) + 'a>
selector: &Selector,
callback: Box<FnMut(&mut Any) + 'a>,
) { ) {
self.wrap_call_on_any(selector, callback) self.wrap_call_on_any(selector, callback)
} }

View File

@ -1,5 +1,3 @@
use {Cursive, Printer, With}; use {Cursive, Printer, With};
use align::HAlign; use align::HAlign;
use direction::Direction; use direction::Direction;

View File

@ -161,7 +161,6 @@ impl<T> Canvas<T> {
self.needs_relayout = Box::new(f); self.needs_relayout = Box::new(f);
} }
/// Sets the closure for `needs_relayout()`. /// Sets the closure for `needs_relayout()`.
/// ///
/// Chainable variant. /// Chainable variant.

View File

@ -8,7 +8,6 @@ use theme::ColorStyle;
use vec::Vec2; use vec::Vec2;
use view::View; use view::View;
/// Checkable box. /// Checkable box.
pub struct Checkbox { pub struct Checkbox {
checked: bool, checked: bool,
@ -116,15 +115,13 @@ impl View for Checkbox {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if self.enabled { if self.enabled {
printer.with_selection( printer.with_selection(printer.focused, |printer| {
printer.focused, self.draw_internal(printer)
|printer| self.draw_internal(printer), });
);
} else { } else {
printer.with_color( printer.with_color(ColorStyle::Secondary, |printer| {
ColorStyle::Secondary, self.draw_internal(printer)
|printer| self.draw_internal(printer), });
);
} }
} }

View File

@ -216,7 +216,6 @@ impl Dialog {
self self
} }
// Private methods // Private methods
// An event is received while the content is in focus // An event is received while the content is in focus
@ -373,10 +372,9 @@ impl Dialog {
printer.print((x + len, 0), ""); printer.print((x + len, 0), "");
}); });
printer.with_color( printer.with_color(ColorStyle::TitlePrimary, |p| {
ColorStyle::TitlePrimary, p.print((x, 0), &self.title)
|p| p.print((x, 0), &self.title), });
);
} }
} }

View File

@ -1,5 +1,3 @@
use {Cursive, Printer, With}; use {Cursive, Printer, With};
use direction::Direction; use direction::Direction;
use event::{Callback, Event, EventResult, Key, MouseEvent}; use event::{Callback, Event, EventResult, Key, MouseEvent};
@ -188,7 +186,6 @@ impl EditView {
self.style = style; self.style = style;
} }
/// Sets the style used for this view. /// Sets the style used for this view.
/// ///
/// When the view is enabled, the style will be reversed. /// When the view is enabled, the style will be reversed.
@ -278,11 +275,11 @@ impl EditView {
// Instead, have some generic function immutify() // Instead, have some generic function immutify()
// or something that wraps a FnMut closure. // or something that wraps a FnMut closure.
let callback = RefCell::new(callback); let callback = RefCell::new(callback);
self.set_on_submit( self.set_on_submit(move |s, text| {
move |s, text| if let Ok(mut f) = callback.try_borrow_mut() { if let Ok(mut f) = callback.try_borrow_mut() {
(&mut *f)(s, text); (&mut *f)(s, text);
}, }
); });
} }
/// Sets a callback to be called when `<Enter>` is pressed. /// Sets a callback to be called when `<Enter>` is pressed.
@ -516,8 +513,7 @@ impl View for EditView {
.next() .next()
.expect(&format!( .expect(&format!(
"Found no char at cursor {} in {}", "Found no char at cursor {} in {}",
self.cursor, self.cursor, &self.content
&self.content
)); ));
if self.secret { if self.secret {
make_small_stars(selected.width()) make_small_stars(selected.width())

View File

@ -192,7 +192,11 @@ impl LinearLayout {
) -> Box<Iterator<Item = (usize, &mut Child)> + 'a> { ) -> Box<Iterator<Item = (usize, &mut Child)> + 'a> {
match source { match source {
direction::Relative::Front => { direction::Relative::Front => {
let start = if from_focus { self.focus } else { 0 }; let start = if from_focus {
self.focus
} else {
0
};
Box::new(self.children.iter_mut().enumerate().skip(start)) Box::new(self.children.iter_mut().enumerate().skip(start))
} }
@ -347,7 +351,6 @@ impl View for LinearLayout {
let ideal = self.orientation.stack(ideal_sizes.iter()); let ideal = self.orientation.stack(ideal_sizes.iter());
debug!("Ideal result: {:?}", ideal); debug!("Ideal result: {:?}", ideal);
// Does it fit? // Does it fit?
if ideal.fits_in(req) { if ideal.fits_in(req) {
// Champagne! // Champagne!

View File

@ -73,7 +73,6 @@ impl ListView {
self.children.is_empty() self.children.is_empty()
} }
/// Returns a reference to the children /// Returns a reference to the children
pub fn children(&self) -> &[ListChild] { pub fn children(&self) -> &[ListChild] {
&self.children[..] &self.children[..]
@ -155,7 +154,11 @@ impl ListView {
) -> Box<Iterator<Item = (usize, &mut ListChild)> + 'a> { ) -> Box<Iterator<Item = (usize, &mut ListChild)> + 'a> {
match source { match source {
direction::Relative::Front => { direction::Relative::Front => {
let start = if from_focus { self.focus } else { 0 }; let start = if from_focus {
self.focus
} else {
0
};
Box::new(self.children.iter_mut().enumerate().skip(start)) Box::new(self.children.iter_mut().enumerate().skip(start))
} }
@ -365,7 +368,6 @@ impl View for ListView {
_ => (), _ => (),
} }
// Then: some events can move the focus around. // Then: some events can move the focus around.
self.check_focus_grab(&event); self.check_focus_grab(&event);

View File

@ -87,7 +87,6 @@ impl MenuPopup {
} }
} }
/// Sets the alignment for this view. /// Sets the alignment for this view.
/// ///
/// Chainable variant. /// Chainable variant.
@ -152,8 +151,8 @@ impl MenuPopup {
let action_cb = action_cb.clone(); let action_cb = action_cb.clone();
s.screen_mut().add_layer_at( s.screen_mut().add_layer_at(
Position::parent(offset), Position::parent(offset),
OnEventView::new( OnEventView::new(MenuPopup::new(Rc::clone(&tree)).on_action(
MenuPopup::new(Rc::clone(&tree)).on_action(move |s| { move |s| {
// This will happen when the subtree popup // This will happen when the subtree popup
// activates something; // activates something;
// First, remove ourselve. // First, remove ourselve.
@ -161,8 +160,8 @@ impl MenuPopup {
if let Some(ref action_cb) = action_cb { if let Some(ref action_cb) = action_cb {
action_cb.clone()(s); action_cb.clone()(s);
} }
}), },
).on_event(Key::Left, |s| s.pop_layer()), )).on_event(Key::Left, |s| s.pop_layer()),
); );
}) })
} }
@ -258,7 +257,6 @@ impl View for MenuPopup {
.unwrap_or(1); .unwrap_or(1);
let h = 2 + self.menu.children.len(); let h = 2 + self.menu.children.len();
let scrolling = req.y < h; let scrolling = req.y < h;
let w = if scrolling { w + 1 } else { w }; let w = if scrolling { w + 1 } else { w };
@ -346,10 +344,13 @@ impl View for MenuPopup {
position.checked_sub(offset + (1, 1)).map( position.checked_sub(offset + (1, 1)).map(
// `position` is not relative to the content // `position` is not relative to the content
// (It's inside the border) // (It's inside the border)
|position| if position < inner_size { |position| {
let focus = position.y + self.scrollbase.start_line; if position < inner_size {
if !self.menu.children[focus].is_delimiter() { let focus =
self.focus = focus; position.y + self.scrollbase.start_line;
if !self.menu.children[focus].is_delimiter() {
self.focus = focus;
}
} }
}, },
); );

View File

@ -82,7 +82,7 @@ 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;
pub use self::slider_view::SliderView; pub use self::slider_view::SliderView;
pub use self::stack_view::{StackView, LayerPosition}; pub use self::stack_view::{LayerPosition, StackView};
pub use self::text_area::TextArea; pub use self::text_area::TextArea;
pub use self::text_view::{TextView, TextContent, TextContentRef}; pub use self::text_view::{TextContent, TextContentRef, TextView};
pub use self::tracked_view::TrackedView; pub use self::tracked_view::TrackedView;

View File

@ -16,7 +16,6 @@ impl<V: View> Panel<V> {
} }
} }
impl<V: View> ViewWrapper for Panel<V> { impl<V: View> ViewWrapper for Panel<V> {
wrap_impl!(self.view: V); wrap_impl!(self.view: V);

View File

@ -1,5 +1,3 @@
use Printer; use Printer;
use align::HAlign; use align::HAlign;
use std::cmp; use std::cmp;
@ -68,7 +66,6 @@ pub struct ProgressBar {
label_maker: Box<Fn(usize, (usize, usize)) -> String>, label_maker: Box<Fn(usize, (usize, usize)) -> String>,
} }
fn make_percentage(value: usize, (min, max): (usize, usize)) -> String { fn make_percentage(value: usize, (min, max): (usize, usize)) -> String {
if value < min { if value < min {
// ?? Negative progress? // ?? Negative progress?

View File

@ -100,7 +100,6 @@ pub struct RadioButton<T> {
label: String, label: String,
} }
impl<T> RadioButton<T> { impl<T> RadioButton<T> {
impl_enabled!(self.enabled); impl_enabled!(self.enabled);
@ -165,15 +164,13 @@ impl<T: 'static> View for RadioButton<T> {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if self.enabled { if self.enabled {
printer.with_selection( printer.with_selection(printer.focused, |printer| {
printer.focused, self.draw_internal(printer)
|printer| self.draw_internal(printer), });
);
} else { } else {
printer.with_color( printer.with_color(ColorStyle::Secondary, |printer| {
ColorStyle::Secondary, self.draw_internal(printer)
|printer| self.draw_internal(printer), });
);
} }
} }

View File

@ -175,7 +175,6 @@ impl<T: 'static> SelectView<T> {
self.with(|s| s.set_on_submit(cb)) self.with(|s| s.set_on_submit(cb))
} }
/// Sets the alignment for this view. /// Sets the alignment for this view.
pub fn align(mut self, align: Align) -> Self { pub fn align(mut self, align: Align) -> Self {
self.align = align; self.align = align;

View File

@ -255,7 +255,7 @@ impl StackView {
} }
/// Moves a layer to a new position in the stack. /// Moves a layer to a new position in the stack.
/// ///
/// This only affects the elevation of a layer (whether it is drawn over /// This only affects the elevation of a layer (whether it is drawn over
/// or under other views). /// or under other views).
pub fn move_layer(&mut self, from: LayerPosition, to: LayerPosition) { pub fn move_layer(&mut self, from: LayerPosition, to: LayerPosition) {
@ -266,11 +266,7 @@ impl StackView {
let removed = self.layers.remove(from_i); let removed = self.layers.remove(from_i);
// Shift the position if needed // Shift the position if needed
let to_i = if to_i > from_i { let to_i = if to_i > from_i { to_i - 1 } else { to_i };
to_i - 1
} else {
to_i
};
self.layers.insert(to_i, removed); self.layers.insert(to_i, removed);
} }
@ -333,8 +329,11 @@ impl View for StackView {
StackPositionIterator::new(self.layers.iter(), printer.size) StackPositionIterator::new(self.layers.iter(), printer.size)
.enumerate() .enumerate()
{ {
v.view v.view.draw(&printer.sub_printer(
.draw(&printer.sub_printer(offset, v.size, i + 1 == last)); offset,
v.size,
i + 1 == last,
));
} }
}); });
} }

View File

@ -423,12 +423,11 @@ impl View for TextArea {
} else { } else {
printer.size.x printer.size.x
}; };
printer.with_effect( printer.with_effect(effect, |printer| {
effect, for y in 0..printer.size.y {
|printer| for y in 0..printer.size.y {
printer.print_hline((0, y), w, " "); printer.print_hline((0, y), w, " ");
}, }
); });
debug!("Content: `{}`", &self.content); debug!("Content: `{}`", &self.content);
self.scrollbase.draw(printer, |printer, i| { self.scrollbase.draw(printer, |printer, i| {

View File

@ -33,6 +33,8 @@ impl TextContent {
/// A reference to the text content. /// A reference to the text content.
/// ///
/// It implements `Deref<Target=str>`.
///
/// This keeps the content locked. Do not store this! /// This keeps the content locked. Do not store this!
pub struct TextContentRef { pub struct TextContentRef {
handle: OwningHandle< handle: OwningHandle<

View File

@ -1,4 +1,3 @@
/// Generic trait to enable chainable API /// Generic trait to enable chainable API
pub trait With: Sized { pub trait With: Sized {
/// Calls the given closure on `self`. /// Calls the given closure on `self`.