mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Update Readme & run rustfmt
This commit is contained in:
parent
8d24df5f59
commit
58bd274df0
12
Readme.md
12
Readme.md
@ -59,8 +59,6 @@ _(Colors may depend on your terminal configuration.)_
|
|||||||
|
|
||||||
First off, terminals are messy. A small set of features is standard, but beyond that, almost every terminal has its own implementation.
|
First off, terminals are messy. A small set of features is standard, but beyond that, almost every terminal has its own implementation.
|
||||||
|
|
||||||
I mostly test VTE-based terminals (Gnome & Xfce), with the occasional Konsole and xterm checks.
|
|
||||||
|
|
||||||
### Output
|
### Output
|
||||||
|
|
||||||
* **Colors**: the basic 8-colors palette should be broadly supported. User-defined colors is not supported in the raw linux TTY, but should work in most terminals, although it's still kinda experimental.
|
* **Colors**: the basic 8-colors palette should be broadly supported. User-defined colors is not supported in the raw linux TTY, but should work in most terminals, although it's still kinda experimental.
|
||||||
@ -73,7 +71,7 @@ Also, Cursive currently expects every codepoint to be a one-column character, so
|
|||||||
* Keep in mind that if the terminal has shortcuts registered, they probably won't be transmitted to the app.
|
* Keep in mind that if the terminal has shortcuts registered, they probably won't be transmitted to the app.
|
||||||
* UTF-8 input should work fine in a unicode-enabled terminal emulator, but raw linux TTY may be more capricious.
|
* UTF-8 input should work fine in a unicode-enabled terminal emulator, but raw linux TTY may be more capricious.
|
||||||
|
|
||||||
Here is the support table for input keys (All means Linux TTY and terminal emulators):
|
Here is the support table for input keys. Tested terminals are mostly Gnome terminal and Linux TTY, xterm, and a few others now and then.
|
||||||
|
|
||||||
| | Key | Shift+Key | Ctrl+Key | Shift+Ctrl+Key |
|
| | Key | Shift+Key | Ctrl+Key | Shift+Ctrl+Key |
|
||||||
|--------------------------|:----:|:----------------------:|:--------------------------:|:---------------:|
|
|--------------------------|:----:|:----------------------:|:--------------------------:|:---------------:|
|
||||||
@ -86,9 +84,10 @@ Here is the support table for input keys (All means Linux TTY and terminal emula
|
|||||||
| Ins | All | None (paste clipboard) | Xterm | None |
|
| Ins | All | None (paste clipboard) | Xterm | None |
|
||||||
| Del | All | VTE+Xterm | VTE+Xterm | VTE+Xterm |
|
| Del | All | VTE+Xterm | VTE+Xterm | VTE+Xterm |
|
||||||
| Home, End | All | Xterm | Xterm | Xterm |
|
| Home, End | All | Xterm | Xterm | Xterm |
|
||||||
| PageUp, PageDown | All | None | Xterm | None |
|
| PageUp, PageDown | All | All | All | None |
|
||||||
| Fn keys: F1-F4 | All | None (WIP) | None (WIP) | None (WIP) |
|
| Fn keys: F1-F4 | All | All except Konsole | Gnome+XTerm | Gnome+Xterm |
|
||||||
| Fn keys: F5-F12 | All | VTE+Xterm (WIP) | VTE+Xterm (WIP) | VTE+Xterm (WIP) |
|
| Fn keys: F5-F8 | All | All | All except TTY | All except TTY |
|
||||||
|
| Fn keys: F9-F12 | All | All except TTY | All except TTY | All except TTY |
|
||||||
| PrtScn, ScrollLock | None | None | None | None |
|
| PrtScn, ScrollLock | None | None | None | None |
|
||||||
| Window, Menu | None | None | None | None |
|
| Window, Menu | None | None | None | None |
|
||||||
|
|
||||||
@ -97,5 +96,6 @@ Here is the support table for input keys (All means Linux TTY and terminal emula
|
|||||||
You want to help? Great! Here is a non-exhaustive list of things you could do:
|
You want to help? Great! Here is a non-exhaustive list of things you could do:
|
||||||
|
|
||||||
* Provide example use-case: a good idea of application for existing or new components.
|
* Provide example use-case: a good idea of application for existing or new components.
|
||||||
|
* Check compatibility: run the `key_codes` example on your favorite terminal, and report the results!
|
||||||
* Test and reports issues: a bug won't get fixed if we don't know it's there.
|
* Test and reports issues: a bug won't get fixed if we don't know it's there.
|
||||||
* Hack the code! If you feel confident with rust, pick an issue you like and hack away!
|
* Hack the code! If you feel confident with rust, pick an issue you like and hack away!
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
extern crate cursive;
|
extern crate cursive;
|
||||||
|
|
||||||
use cursive::Cursive;
|
use cursive::Cursive;
|
||||||
use cursive::view::{IdView,TextView,Dialog,KeyEventView};
|
use cursive::view::{IdView, TextView, Dialog, KeyEventView};
|
||||||
|
|
||||||
fn show_popup(siv: &mut Cursive) {
|
fn show_popup(siv: &mut Cursive) {
|
||||||
|
|
||||||
siv.add_layer(Dialog::new(TextView::new("Tak!"))
|
siv.add_layer(Dialog::new(TextView::new("Tak!"))
|
||||||
.button("Change", |s| {
|
.button("Change", |s| {
|
||||||
// Look for a view tagged "text". We _know_ it's there, so unwrap it.
|
// Look for a view tagged "text". We _know_ it's there, so unwrap it.
|
||||||
let view = s.find_id::<TextView>("text").unwrap();
|
let view = s.find_id::<TextView>("text").unwrap();
|
||||||
let content: String = view.get_content().chars().rev().collect();
|
let content: String = view.get_content().chars().rev().collect();
|
||||||
view.set_content(&content);
|
view.set_content(&content);
|
||||||
})
|
})
|
||||||
.dismiss_button("Ok"));
|
.dismiss_button("Ok"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ fn main() {
|
|||||||
// We add the P callback on the textview only (and not globally),
|
// We add the P callback on the textview only (and not globally),
|
||||||
// so that we can't call it when the popup is already visible.
|
// so that we can't call it when the popup is already visible.
|
||||||
siv.add_layer(KeyEventView::new(IdView::new("text", TextView::new(content)))
|
siv.add_layer(KeyEventView::new(IdView::new("text", TextView::new(content)))
|
||||||
.register('p', |s| show_popup(s)));
|
.register('p', |s| show_popup(s)));
|
||||||
|
|
||||||
|
|
||||||
siv.run();
|
siv.run();
|
||||||
|
102
src/event.rs
102
src/event.rs
@ -131,15 +131,15 @@ impl Key {
|
|||||||
ncurses::KEY_SEND => Key::ShiftEnd,
|
ncurses::KEY_SEND => Key::ShiftEnd,
|
||||||
ncurses::KEY_SDC => Key::ShiftDel,
|
ncurses::KEY_SDC => Key::ShiftDel,
|
||||||
// All Fn keys use the same enum with associated number
|
// All Fn keys use the same enum with associated number
|
||||||
f @ ncurses::KEY_F1 ... ncurses::KEY_F15 => Key::F((f - ncurses::KEY_F0) as u8),
|
f @ ncurses::KEY_F1...ncurses::KEY_F12 => Key::F((f - ncurses::KEY_F0) as u8),
|
||||||
f @ 281 ... 291 => Key::ShiftF((f - 281 + 5) as u8),
|
f @ 277...288 => Key::ShiftF((f - 281 + 5) as u8),
|
||||||
f @ 293 ... 303 => Key::CtrlF((f - 293 + 5) as u8),
|
f @ 289...300 => Key::CtrlF((f - 293 + 5) as u8),
|
||||||
f @ 305 ... 315 => Key::CtrlShiftF((f - 305 + 5) as u8),
|
f @ 301...312 => Key::CtrlShiftF((f - 305 + 5) as u8),
|
||||||
// Shift and Ctrl F{1-4} need escape sequences...
|
// Shift and Ctrl F{1-4} need escape sequences...
|
||||||
//
|
//
|
||||||
// TODO: shift and ctrl Fn keys
|
// TODO: shift and ctrl Fn keys
|
||||||
// Avoids 8-10 (H,I,J), they are used by other commands.
|
// Avoids 8-10 (H,I,J), they are used by other commands.
|
||||||
c @ 1 ... 7 | c @ 11 ... 25 => Key::CtrlChar(('a' as u8 + (c - 1) as u8) as char),
|
c @ 1...7 | c @ 11...25 => Key::CtrlChar(('a' as u8 + (c - 1) as u8) as char),
|
||||||
_ => Key::Unknown(ch),
|
_ => Key::Unknown(ch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,51 +154,53 @@ impl fmt::Display for Key {
|
|||||||
Key::ShiftF(n) => write!(f, "Shift-F{}", n),
|
Key::ShiftF(n) => write!(f, "Shift-F{}", n),
|
||||||
Key::CtrlF(n) => write!(f, "Ctrl-F{}", n),
|
Key::CtrlF(n) => write!(f, "Ctrl-F{}", n),
|
||||||
Key::CtrlShiftF(n) => write!(f, "Ctrl-Shift-F{}", n),
|
Key::CtrlShiftF(n) => write!(f, "Ctrl-Shift-F{}", n),
|
||||||
key => write!(f,
|
key => {
|
||||||
"{}",
|
write!(f,
|
||||||
match key {
|
"{}",
|
||||||
Key::NumpadCenter => "Numpad center",
|
match key {
|
||||||
Key::Left => "Left",
|
Key::NumpadCenter => "Numpad center",
|
||||||
Key::Right => "Right",
|
Key::Left => "Left",
|
||||||
Key::Down => "Down",
|
Key::Right => "Right",
|
||||||
Key::Up => "Up",
|
Key::Down => "Down",
|
||||||
Key::CtrlShiftLeft => "Ctrl-Shift-Left",
|
Key::Up => "Up",
|
||||||
Key::CtrlShiftRight => "Ctrl-Shift-Right",
|
Key::CtrlShiftLeft => "Ctrl-Shift-Left",
|
||||||
Key::CtrlShiftUp => "Ctrl-Shift-Up",
|
Key::CtrlShiftRight => "Ctrl-Shift-Right",
|
||||||
Key::CtrlShiftDown => "Ctrl-Shift-Down",
|
Key::CtrlShiftUp => "Ctrl-Shift-Up",
|
||||||
Key::ShiftUp => "Shift-Up",
|
Key::CtrlShiftDown => "Ctrl-Shift-Down",
|
||||||
Key::ShiftDown => "Shift-Down",
|
Key::ShiftUp => "Shift-Up",
|
||||||
Key::ShiftLeft => "Shift-Left",
|
Key::ShiftDown => "Shift-Down",
|
||||||
Key::ShiftRight => "Shift-Right",
|
Key::ShiftLeft => "Shift-Left",
|
||||||
Key::ShiftDel => "Shift-Del",
|
Key::ShiftRight => "Shift-Right",
|
||||||
Key::CtrlDel => "Ctrl-Del",
|
Key::ShiftDel => "Shift-Del",
|
||||||
Key::CtrlShiftDel => "Ctrl-Shift-Del",
|
Key::CtrlDel => "Ctrl-Del",
|
||||||
Key::CtrlLeft => "Ctrl-Left",
|
Key::CtrlShiftDel => "Ctrl-Shift-Del",
|
||||||
Key::CtrlRight => "Ctrl-Right",
|
Key::CtrlLeft => "Ctrl-Left",
|
||||||
Key::CtrlUp => "Ctrl-Up",
|
Key::CtrlRight => "Ctrl-Right",
|
||||||
Key::CtrlDown => "Ctrl-Down",
|
Key::CtrlUp => "Ctrl-Up",
|
||||||
Key::CtrlPageUp => "Ctrl-PageUp",
|
Key::CtrlDown => "Ctrl-Down",
|
||||||
Key::CtrlPageDown => "Ctrl-PageDown",
|
Key::CtrlPageUp => "Ctrl-PageUp",
|
||||||
Key::PageUp => "PageUp",
|
Key::CtrlPageDown => "Ctrl-PageDown",
|
||||||
Key::PageDown => "PageDown",
|
Key::PageUp => "PageUp",
|
||||||
Key::Home => "Home",
|
Key::PageDown => "PageDown",
|
||||||
Key::ShiftHome => "Shift-Home",
|
Key::Home => "Home",
|
||||||
Key::CtrlHome => "Ctrl-Home",
|
Key::ShiftHome => "Shift-Home",
|
||||||
Key::CtrlShiftHome => "Ctrl-Shift-Home",
|
Key::CtrlHome => "Ctrl-Home",
|
||||||
Key::End => "End",
|
Key::CtrlShiftHome => "Ctrl-Shift-Home",
|
||||||
Key::ShiftEnd => "Shift-End",
|
Key::End => "End",
|
||||||
Key::CtrlEnd => "Ctrl-End",
|
Key::ShiftEnd => "Shift-End",
|
||||||
Key::CtrlShiftEnd => "Ctrl-Shift-End",
|
Key::CtrlEnd => "Ctrl-End",
|
||||||
Key::Backspace => "Backspace",
|
Key::CtrlShiftEnd => "Ctrl-Shift-End",
|
||||||
Key::Del => "Del",
|
Key::Backspace => "Backspace",
|
||||||
Key::Enter => "Enter",
|
Key::Del => "Del",
|
||||||
Key::ShiftTab => "Shift-Tab",
|
Key::Enter => "Enter",
|
||||||
Key::Tab => "Tab",
|
Key::ShiftTab => "Shift-Tab",
|
||||||
Key::Ins => "Ins",
|
Key::Tab => "Tab",
|
||||||
Key::CtrlIns => "Ctrl-Ins",
|
Key::Ins => "Ins",
|
||||||
Key::Esc => "Esc",
|
Key::CtrlIns => "Ctrl-Ins",
|
||||||
_ => "Missing key label",
|
Key::Esc => "Esc",
|
||||||
}),
|
_ => "Missing key label",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/theme.rs
34
src/theme.rs
@ -86,10 +86,12 @@ impl Theme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match table.get("borders") {
|
match table.get("borders") {
|
||||||
Some(&toml::Value::String(ref borders)) => match BorderStyle::from(borders) {
|
Some(&toml::Value::String(ref borders)) => {
|
||||||
Some(borders) => self.borders = borders,
|
match BorderStyle::from(borders) {
|
||||||
None => (),
|
Some(borders) => self.borders = borders,
|
||||||
},
|
None => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,14 +263,18 @@ impl Color {
|
|||||||
Some(&toml::Value::String(ref value)) => {
|
Some(&toml::Value::String(ref value)) => {
|
||||||
self.load_value(value, new_id);
|
self.load_value(value, new_id);
|
||||||
}
|
}
|
||||||
Some(&toml::Value::Array(ref array)) => for color in array.iter() {
|
Some(&toml::Value::Array(ref array)) => {
|
||||||
match color {
|
for color in array.iter() {
|
||||||
&toml::Value::String(ref color) => if self.load_value(color, new_id) {
|
match color {
|
||||||
return;
|
&toml::Value::String(ref color) => {
|
||||||
},
|
if self.load_value(color, new_id) {
|
||||||
_ => (),
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,9 +417,9 @@ fn load_hex(s: &str) -> i16 {
|
|||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
sum *= 16;
|
sum *= 16;
|
||||||
sum += match c {
|
sum += match c {
|
||||||
n @ '0' ... '9' => n as i16 - '0' as i16,
|
n @ '0'...'9' => n as i16 - '0' as i16,
|
||||||
n @ 'a' ... 'f' => n as i16 - 'a' as i16 + 10,
|
n @ 'a'...'f' => n as i16 - 'a' as i16 + 10,
|
||||||
n @ 'A' ... 'F' => n as i16 - 'A' as i16 + 10,
|
n @ 'A'...'F' => n as i16 - 'A' as i16 + 10,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ pub fn read_char<F>(first: u8, next: F) -> Result<char, String>
|
|||||||
|
|
||||||
// Number of leading 1s determines the number of bytes we'll have to read
|
// Number of leading 1s determines the number of bytes we'll have to read
|
||||||
let n_bytes = match (!first).leading_zeros() {
|
let n_bytes = match (!first).leading_zeros() {
|
||||||
n @ 2 ... 6 => n as usize,
|
n @ 2...6 => n as usize,
|
||||||
1 => return Err("First byte is continuation byte.".to_string()),
|
1 => return Err("First byte is continuation byte.".to_string()),
|
||||||
7...8 => return Err("WTF is this byte??".to_string()),
|
7...8 => return Err("WTF is this byte??".to_string()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
18
src/vec.rs
18
src/vec.rs
@ -80,25 +80,25 @@ impl ToVec2 for Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToVec2 for (i32,i32) {
|
impl ToVec2 for (i32, i32) {
|
||||||
fn to_vec2(self) -> Vec2 {
|
fn to_vec2(self) -> Vec2 {
|
||||||
(self.0 as usize, self.1 as usize).to_vec2()
|
(self.0 as usize, self.1 as usize).to_vec2()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToVec2 for (usize,usize) {
|
impl ToVec2 for (usize, usize) {
|
||||||
fn to_vec2(self) -> Vec2 {
|
fn to_vec2(self) -> Vec2 {
|
||||||
Vec2::new(self.0, self.1)
|
Vec2::new(self.0, self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToVec2 for (u32,u32) {
|
impl ToVec2 for (u32, u32) {
|
||||||
fn to_vec2(self) -> Vec2 {
|
fn to_vec2(self) -> Vec2 {
|
||||||
Vec2::new(self.0 as usize, self.1 as usize)
|
Vec2::new(self.0 as usize, self.1 as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: ToVec2> Add<T> for Vec2 {
|
impl<T: ToVec2> Add<T> for Vec2 {
|
||||||
type Output = Vec2;
|
type Output = Vec2;
|
||||||
|
|
||||||
fn add(self, other: T) -> Vec2 {
|
fn add(self, other: T) -> Vec2 {
|
||||||
@ -110,7 +110,7 @@ impl <T: ToVec2> Add<T> for Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: ToVec2> Sub<T> for Vec2 {
|
impl<T: ToVec2> Sub<T> for Vec2 {
|
||||||
type Output = Vec2;
|
type Output = Vec2;
|
||||||
|
|
||||||
fn sub(self, other: T) -> Vec2 {
|
fn sub(self, other: T) -> Vec2 {
|
||||||
@ -206,13 +206,13 @@ impl ToVec4 for Vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToVec4 for (usize,usize,usize,usize) {
|
impl ToVec4 for (usize, usize, usize, usize) {
|
||||||
fn to_vec4(self) -> Vec4 {
|
fn to_vec4(self) -> Vec4 {
|
||||||
Vec4::new(self.0, self.1, self.2, self.3)
|
Vec4::new(self.0, self.1, self.2, self.3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToVec4 for (i32,i32,i32,i32) {
|
impl ToVec4 for (i32, i32, i32, i32) {
|
||||||
fn to_vec4(self) -> Vec4 {
|
fn to_vec4(self) -> Vec4 {
|
||||||
Vec4::new(self.0 as usize,
|
Vec4::new(self.0 as usize,
|
||||||
self.1 as usize,
|
self.1 as usize,
|
||||||
@ -221,7 +221,7 @@ impl ToVec4 for (i32,i32,i32,i32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: ToVec4> Add<T> for Vec4 {
|
impl<T: ToVec4> Add<T> for Vec4 {
|
||||||
type Output = Vec4;
|
type Output = Vec4;
|
||||||
|
|
||||||
fn add(self, other: T) -> Vec4 {
|
fn add(self, other: T) -> Vec4 {
|
||||||
@ -236,7 +236,7 @@ impl <T: ToVec4> Add<T> for Vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: ToVec4> Sub<T> for Vec4 {
|
impl<T: ToVec4> Sub<T> for Vec4 {
|
||||||
type Output = Vec4;
|
type Output = Vec4;
|
||||||
|
|
||||||
fn sub(self, other: T) -> Vec4 {
|
fn sub(self, other: T) -> Vec4 {
|
||||||
|
@ -7,7 +7,7 @@ pub struct BoxView<T: View> {
|
|||||||
view: T,
|
view: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> BoxView<T> {
|
impl<T: View> BoxView<T> {
|
||||||
/// Creates a new BoxView with the given minimum size and content
|
/// Creates a new BoxView with the given minimum size and content
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -25,8 +25,7 @@ impl <T: View> BoxView<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> ViewWrapper for BoxView<T> {
|
impl<T: View> ViewWrapper for BoxView<T> {
|
||||||
|
|
||||||
wrap_impl!(&self.view);
|
wrap_impl!(&self.view);
|
||||||
|
|
||||||
fn wrap_get_min_size(&self, mut req: SizeRequest) -> Vec2 {
|
fn wrap_get_min_size(&self, mut req: SizeRequest) -> Vec2 {
|
||||||
|
@ -27,7 +27,6 @@ impl Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl View for Button {
|
impl View for Button {
|
||||||
|
|
||||||
fn draw(&mut self, printer: &Printer) {
|
fn draw(&mut self, printer: &Printer) {
|
||||||
let style = if !printer.focused {
|
let style = if !printer.focused {
|
||||||
ColorPair::Primary
|
ColorPair::Primary
|
||||||
|
@ -97,7 +97,6 @@ impl Dialog {
|
|||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for Dialog {
|
impl View for Dialog {
|
||||||
@ -207,54 +206,62 @@ impl View for Dialog {
|
|||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
match self.focus {
|
match self.focus {
|
||||||
// If we are on the content, we can only go down.
|
// If we are on the content, we can only go down.
|
||||||
Focus::Content => match self.content.on_event(event) {
|
Focus::Content => {
|
||||||
EventResult::Ignored if !self.buttons.is_empty() => match event {
|
match self.content.on_event(event) {
|
||||||
Event::KeyEvent(Key::Down) => {
|
EventResult::Ignored if !self.buttons.is_empty() => {
|
||||||
// Default to leftmost button when going down.
|
match event {
|
||||||
self.focus = Focus::Button(0);
|
Event::KeyEvent(Key::Down) => {
|
||||||
EventResult::Consumed(None)
|
// Default to leftmost button when going down.
|
||||||
|
self.focus = Focus::Button(0);
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => {
|
||||||
|
self.focus = Focus::Button(0);
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
_ => EventResult::Ignored,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => {
|
res => res,
|
||||||
self.focus = Focus::Button(0);
|
}
|
||||||
EventResult::Consumed(None)
|
}
|
||||||
}
|
|
||||||
_ => EventResult::Ignored,
|
|
||||||
},
|
|
||||||
res => res,
|
|
||||||
},
|
|
||||||
// If we are on a button, we have more choice
|
// If we are on a button, we have more choice
|
||||||
Focus::Button(i) => match self.buttons[i].on_event(event) {
|
Focus::Button(i) => {
|
||||||
EventResult::Ignored => match event {
|
match self.buttons[i].on_event(event) {
|
||||||
// Up goes back to the content
|
EventResult::Ignored => {
|
||||||
Event::KeyEvent(Key::Up) => {
|
match event {
|
||||||
if self.content.take_focus() {
|
// Up goes back to the content
|
||||||
self.focus = Focus::Content;
|
Event::KeyEvent(Key::Up) => {
|
||||||
EventResult::Consumed(None)
|
if self.content.take_focus() {
|
||||||
} else {
|
self.focus = Focus::Content;
|
||||||
EventResult::Ignored
|
EventResult::Consumed(None)
|
||||||
|
} else {
|
||||||
|
EventResult::Ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => {
|
||||||
|
if self.content.take_focus() {
|
||||||
|
self.focus = Focus::Content;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
} else {
|
||||||
|
EventResult::Ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Left and Right move to other buttons
|
||||||
|
Event::KeyEvent(Key::Right) if i + 1 < self.buttons.len() => {
|
||||||
|
self.focus = Focus::Button(i + 1);
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Left) if i > 0 => {
|
||||||
|
self.focus = Focus::Button(i - 1);
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
_ => EventResult::Ignored,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => {
|
res => res,
|
||||||
if self.content.take_focus() {
|
}
|
||||||
self.focus = Focus::Content;
|
}
|
||||||
EventResult::Consumed(None)
|
|
||||||
} else {
|
|
||||||
EventResult::Ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Left and Right move to other buttons
|
|
||||||
Event::KeyEvent(Key::Right) if i + 1 < self.buttons.len() => {
|
|
||||||
self.focus = Focus::Button(i + 1);
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
Event::KeyEvent(Key::Left) if i > 0 => {
|
|
||||||
self.focus = Focus::Button(i - 1);
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
_ => EventResult::Ignored,
|
|
||||||
},
|
|
||||||
res => res,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ impl EditView {
|
|||||||
cursor: 0,
|
cursor: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
min_length: 1,
|
min_length: 1,
|
||||||
last_length: 0, /* scrollable: false, */
|
last_length: 0, // scrollable: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,20 +138,22 @@ impl View for EditView {
|
|||||||
// TODO: handle wide (CJK) chars
|
// TODO: handle wide (CJK) chars
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
}
|
}
|
||||||
Event::KeyEvent(key) => match key {
|
Event::KeyEvent(key) => {
|
||||||
Key::Home => self.cursor = 0,
|
match key {
|
||||||
Key::End => self.cursor = self.content.chars().count(),
|
Key::Home => self.cursor = 0,
|
||||||
Key::Left if self.cursor > 0 => self.cursor -= 1,
|
Key::End => self.cursor = self.content.chars().count(),
|
||||||
Key::Right if self.cursor < self.content.chars().count() => self.cursor += 1,
|
Key::Left if self.cursor > 0 => self.cursor -= 1,
|
||||||
Key::Backspace if self.cursor > 0 => {
|
Key::Right if self.cursor < self.content.chars().count() => self.cursor += 1,
|
||||||
self.cursor -= 1;
|
Key::Backspace if self.cursor > 0 => {
|
||||||
remove_char(&mut self.content, self.cursor);
|
self.cursor -= 1;
|
||||||
|
remove_char(&mut self.content, self.cursor);
|
||||||
|
}
|
||||||
|
Key::Del if self.cursor < self.content.chars().count() => {
|
||||||
|
remove_char(&mut self.content, self.cursor);
|
||||||
|
}
|
||||||
|
_ => return EventResult::Ignored,
|
||||||
}
|
}
|
||||||
Key::Del if self.cursor < self.content.chars().count() => {
|
}
|
||||||
remove_char(&mut self.content, self.cursor);
|
|
||||||
}
|
|
||||||
_ => return EventResult::Ignored,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep cursor in [offset, offset+last_length] by changing offset
|
// Keep cursor in [offset, offset+last_length] by changing offset
|
||||||
|
@ -6,14 +6,14 @@ pub struct FullView<T: View> {
|
|||||||
view: T,
|
view: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> FullView<T> {
|
impl<T: View> FullView<T> {
|
||||||
/// Wraps the given view into a new FullView.
|
/// Wraps the given view into a new FullView.
|
||||||
pub fn new(view: T) -> Self {
|
pub fn new(view: T) -> Self {
|
||||||
FullView { view: view }
|
FullView { view: view }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> ViewWrapper for FullView<T> {
|
impl<T: View> ViewWrapper for FullView<T> {
|
||||||
wrap_impl!(&self.view);
|
wrap_impl!(&self.view);
|
||||||
|
|
||||||
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||||
|
@ -18,7 +18,7 @@ impl<T: View> IdView<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View + Any> ViewWrapper for IdView<T> {
|
impl<T: View + Any> ViewWrapper for IdView<T> {
|
||||||
wrap_impl!(&self.view);
|
wrap_impl!(&self.view);
|
||||||
|
|
||||||
fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> {
|
fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> {
|
||||||
|
@ -33,17 +33,17 @@ impl KeyEventView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ViewWrapper for KeyEventView {
|
impl ViewWrapper for KeyEventView {
|
||||||
|
|
||||||
wrap_impl!(self.content);
|
wrap_impl!(self.content);
|
||||||
|
|
||||||
fn wrap_on_event(&mut self, event: Event) -> EventResult {
|
fn wrap_on_event(&mut self, event: Event) -> EventResult {
|
||||||
match self.content.on_event(event) {
|
match self.content.on_event(event) {
|
||||||
EventResult::Ignored => match self.callbacks.get(&event) {
|
EventResult::Ignored => {
|
||||||
None => EventResult::Ignored,
|
match self.callbacks.get(&event) {
|
||||||
Some(cb) => EventResult::Consumed(Some(cb.clone())),
|
None => EventResult::Ignored,
|
||||||
},
|
Some(cb) => EventResult::Consumed(Some(cb.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
res => res,
|
res => res,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -180,37 +180,39 @@ impl View for LinearLayout {
|
|||||||
|
|
||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
match self.children[self.focus].view.on_event(event) {
|
match self.children[self.focus].view.on_event(event) {
|
||||||
EventResult::Ignored => match event {
|
EventResult::Ignored => {
|
||||||
Event::KeyEvent(Key::Tab) if self.focus > 0 => {
|
match event {
|
||||||
self.focus -= 1;
|
Event::KeyEvent(Key::Tab) if self.focus > 0 => {
|
||||||
EventResult::Consumed(None)
|
self.focus -= 1;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::ShiftTab) if self.focus + 1 < self.children.len() => {
|
||||||
|
self.focus += 1;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Left) if self.orientation == Orientation::Horizontal &&
|
||||||
|
self.focus > 0 => {
|
||||||
|
self.focus -= 1;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Up) if self.orientation == Orientation::Vertical &&
|
||||||
|
self.focus > 0 => {
|
||||||
|
self.focus -= 1;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Right) if self.orientation == Orientation::Horizontal &&
|
||||||
|
self.focus + 1 < self.children.len() => {
|
||||||
|
self.focus += 1;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
Event::KeyEvent(Key::Down) if self.orientation == Orientation::Vertical &&
|
||||||
|
self.focus + 1 < self.children.len() => {
|
||||||
|
self.focus += 1;
|
||||||
|
EventResult::Consumed(None)
|
||||||
|
}
|
||||||
|
_ => EventResult::Ignored,
|
||||||
}
|
}
|
||||||
Event::KeyEvent(Key::ShiftTab) if self.focus + 1 < self.children.len() => {
|
}
|
||||||
self.focus += 1;
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
Event::KeyEvent(Key::Left) if self.orientation == Orientation::Horizontal &&
|
|
||||||
self.focus > 0 => {
|
|
||||||
self.focus -= 1;
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
Event::KeyEvent(Key::Up) if self.orientation == Orientation::Vertical &&
|
|
||||||
self.focus > 0 => {
|
|
||||||
self.focus -= 1;
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
Event::KeyEvent(Key::Right) if self.orientation == Orientation::Horizontal &&
|
|
||||||
self.focus + 1 < self.children.len() => {
|
|
||||||
self.focus += 1;
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
Event::KeyEvent(Key::Down) if self.orientation == Orientation::Vertical &&
|
|
||||||
self.focus + 1 < self.children.len() => {
|
|
||||||
self.focus += 1;
|
|
||||||
EventResult::Consumed(None)
|
|
||||||
}
|
|
||||||
_ => EventResult::Ignored,
|
|
||||||
},
|
|
||||||
res => res,
|
res => res,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,7 @@ pub trait View {
|
|||||||
|
|
||||||
/// Called once the size for this view has been decided, so it can
|
/// Called once the size for this view has been decided, so it can
|
||||||
/// propagate the information to its children.
|
/// propagate the information to its children.
|
||||||
fn layout(&mut self, Vec2) {
|
fn layout(&mut self, Vec2) {}
|
||||||
}
|
|
||||||
|
|
||||||
/// Draws the view with the given printer (includes bounds) and focus.
|
/// Draws the view with the given printer (includes bounds) and focus.
|
||||||
fn draw(&mut self, printer: &Printer);
|
fn draw(&mut self, printer: &Printer);
|
||||||
|
@ -16,7 +16,7 @@ struct Item<T> {
|
|||||||
value: Rc<T>,
|
value: Rc<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T> Item<T> {
|
impl<T> Item<T> {
|
||||||
fn new(label: &str, value: T) -> Self {
|
fn new(label: &str, value: T) -> Self {
|
||||||
Item {
|
Item {
|
||||||
label: label.to_string(),
|
label: label.to_string(),
|
||||||
@ -36,7 +36,7 @@ pub struct SelectView<T = String> {
|
|||||||
align: Align,
|
align: Align,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: 'static> SelectView<T> {
|
impl<T: 'static> SelectView<T> {
|
||||||
/// Creates a new empty SelectView.
|
/// Creates a new empty SelectView.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SelectView {
|
SelectView {
|
||||||
@ -118,10 +118,9 @@ impl SelectView<String> {
|
|||||||
pub fn item_str(self, label: &str) -> Self {
|
pub fn item_str(self, label: &str) -> Self {
|
||||||
self.item(label, label.to_string())
|
self.item(label, label.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: 'static> View for SelectView<T> {
|
impl<T: 'static> View for SelectView<T> {
|
||||||
fn draw(&mut self, printer: &Printer) {
|
fn draw(&mut self, printer: &Printer) {
|
||||||
|
|
||||||
let h = self.items.len();
|
let h = self.items.len();
|
||||||
@ -175,8 +174,9 @@ impl <T: 'static> View for SelectView<T> {
|
|||||||
Event::KeyEvent(Key::Up) if self.focus > 0 => self.focus -= 1,
|
Event::KeyEvent(Key::Up) if self.focus > 0 => self.focus -= 1,
|
||||||
Event::KeyEvent(Key::Down) if self.focus + 1 < self.items.len() => self.focus += 1,
|
Event::KeyEvent(Key::Down) if self.focus + 1 < self.items.len() => self.focus += 1,
|
||||||
Event::KeyEvent(Key::PageUp) => self.focus -= min(self.focus, 10),
|
Event::KeyEvent(Key::PageUp) => self.focus -= min(self.focus, 10),
|
||||||
Event::KeyEvent(Key::PageDown) =>
|
Event::KeyEvent(Key::PageDown) => {
|
||||||
self.focus = min(self.focus + 10, self.items.len() - 1),
|
self.focus = min(self.focus + 10, self.items.len() - 1)
|
||||||
|
}
|
||||||
Event::KeyEvent(Key::Home) => self.focus = 0,
|
Event::KeyEvent(Key::Home) => self.focus = 0,
|
||||||
Event::KeyEvent(Key::End) => self.focus = self.items.len() - 1,
|
Event::KeyEvent(Key::End) => self.focus = self.items.len() - 1,
|
||||||
Event::KeyEvent(Key::Enter) if self.select_cb.is_some() => {
|
Event::KeyEvent(Key::Enter) if self.select_cb.is_some() => {
|
||||||
|
@ -11,15 +11,14 @@ pub struct ShadowView<T: View> {
|
|||||||
view: T,
|
view: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> ShadowView<T> {
|
impl<T: View> ShadowView<T> {
|
||||||
/// Wraps the given view.
|
/// Wraps the given view.
|
||||||
pub fn new(view: T) -> Self {
|
pub fn new(view: T) -> Self {
|
||||||
ShadowView { view: view }
|
ShadowView { view: view }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> ViewWrapper for ShadowView<T> {
|
impl<T: View> ViewWrapper for ShadowView<T> {
|
||||||
|
|
||||||
wrap_impl!(&self.view);
|
wrap_impl!(&self.view);
|
||||||
|
|
||||||
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
|
||||||
|
@ -20,7 +20,7 @@ impl<T: View> SizedView<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: View> ViewWrapper for SizedView<T> {
|
impl<T: View> ViewWrapper for SizedView<T> {
|
||||||
wrap_impl!(&self.view);
|
wrap_impl!(&self.view);
|
||||||
|
|
||||||
fn wrap_layout(&mut self, size: Vec2) {
|
fn wrap_layout(&mut self, size: Vec2) {
|
||||||
|
@ -134,7 +134,7 @@ struct LinesIterator<'a> {
|
|||||||
width: usize,
|
width: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> LinesIterator<'a> {
|
impl<'a> LinesIterator<'a> {
|
||||||
// Start an iterator on the given content.
|
// Start an iterator on the given content.
|
||||||
fn new(content: &'a str, width: usize) -> Self {
|
fn new(content: &'a str, width: usize) -> Self {
|
||||||
LinesIterator {
|
LinesIterator {
|
||||||
@ -145,8 +145,7 @@ impl <'a> LinesIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> Iterator for LinesIterator<'a> {
|
impl<'a> Iterator for LinesIterator<'a> {
|
||||||
|
|
||||||
type Item = Row;
|
type Item = Row;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Row> {
|
fn next(&mut self) -> Option<Row> {
|
||||||
@ -230,10 +229,12 @@ impl View for TextView {
|
|||||||
match event {
|
match event {
|
||||||
Event::KeyEvent(Key::Home) => self.scrollbase.scroll_top(),
|
Event::KeyEvent(Key::Home) => self.scrollbase.scroll_top(),
|
||||||
Event::KeyEvent(Key::End) => self.scrollbase.scroll_bottom(),
|
Event::KeyEvent(Key::End) => self.scrollbase.scroll_bottom(),
|
||||||
Event::KeyEvent(Key::Up) if self.scrollbase.can_scroll_up() =>
|
Event::KeyEvent(Key::Up) if self.scrollbase.can_scroll_up() => {
|
||||||
self.scrollbase.scroll_up(1),
|
self.scrollbase.scroll_up(1)
|
||||||
Event::KeyEvent(Key::Down) if self.scrollbase.can_scroll_down() =>
|
}
|
||||||
self.scrollbase.scroll_down(1),
|
Event::KeyEvent(Key::Down) if self.scrollbase.can_scroll_down() => {
|
||||||
|
self.scrollbase.scroll_down(1)
|
||||||
|
}
|
||||||
Event::KeyEvent(Key::PageDown) => self.scrollbase.scroll_down(10),
|
Event::KeyEvent(Key::PageDown) => self.scrollbase.scroll_down(10),
|
||||||
Event::KeyEvent(Key::PageUp) => self.scrollbase.scroll_up(10),
|
Event::KeyEvent(Key::PageUp) => self.scrollbase.scroll_up(10),
|
||||||
_ => return EventResult::Ignored,
|
_ => return EventResult::Ignored,
|
||||||
|
@ -23,7 +23,7 @@ pub trait ToPath {
|
|||||||
fn to_path(self) -> ViewPath;
|
fn to_path(self) -> ViewPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> ToPath for &'a [usize] {
|
impl<'a> ToPath for &'a [usize] {
|
||||||
fn to_path(self) -> ViewPath {
|
fn to_path(self) -> ViewPath {
|
||||||
ViewPath { path: self.to_owned() }
|
ViewPath { path: self.to_owned() }
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ pub trait ViewWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T: ViewWrapper> View for T {
|
impl<T: ViewWrapper> View for T {
|
||||||
fn draw(&mut self, printer: &Printer) {
|
fn draw(&mut self, printer: &Printer) {
|
||||||
self.wrap_draw(printer);
|
self.wrap_draw(printer);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user