From 07c3c99e541058ffb319a1fc37d534982d2ec128 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Tue, 15 Mar 2016 15:37:57 -0700 Subject: [PATCH] Update for new ncurses version --- Cargo.toml | 2 +- examples/logs.rs | 3 +- src/align.rs | 9 ++-- src/div.rs | 7 ++- src/event.rs | 94 +++++++++++++++++++------------------- src/lib.rs | 14 +++--- src/orientation.rs | 8 ++-- src/printer.rs | 37 +++++++++------ src/theme.rs | 66 ++++++++++++++++---------- src/utf8.rs | 6 +-- src/vec.rs | 32 +++++++------ src/view/box_view.rs | 20 +++++--- src/view/button.rs | 16 ++++--- src/view/dialog.rs | 75 +++++++++++++++--------------- src/view/edit_view.rs | 48 +++++++++++-------- src/view/full_view.rs | 8 ++-- src/view/id_view.rs | 2 +- src/view/key_event_view.rs | 8 ++-- src/view/linear_layout.rs | 63 +++++++++++++++---------- src/view/mod.rs | 26 +++++++---- src/view/request.rs | 2 - src/view/scroll.rs | 28 ++++++++---- src/view/select_view.rs | 56 +++++++++++++---------- src/view/shadow_view.rs | 27 +++++------ src/view/sized_view.rs | 2 +- src/view/stack_view.rs | 19 ++++---- src/view/text_view.rs | 39 ++++++++-------- src/view/view_path.rs | 8 +--- src/view/view_wrapper.rs | 5 +- 29 files changed, 408 insertions(+), 322 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b6d3f3b..cd7f933 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ version = "0.1.0" [dependencies] ncurses = "5.80.0" -toml = "0.1.25" +toml = "0.1" [[example]] name = "hello_world" diff --git a/examples/logs.rs b/examples/logs.rs index 4f7eaf2..7caf293 100644 --- a/examples/logs.rs +++ b/examples/logs.rs @@ -2,6 +2,7 @@ extern crate cursive; use std::sync::mpsc; use std::thread; +use std::time::Duration; use cursive::Cursive; use cursive::printer::Printer; @@ -42,7 +43,7 @@ fn generate_logs(tx: mpsc::Sender) { Err(_) => return, Ok(_) => (), } - thread::sleep_ms(30); + thread::sleep(Duration::from_millis(30)); } } diff --git a/src/align.rs b/src/align.rs index dac83ec..b30672d 100644 --- a/src/align.rs +++ b/src/align.rs @@ -9,10 +9,7 @@ pub struct Align { impl Align { /// Creates a new Align object from the given horizontal and vertical alignments. pub fn new(h: HAlign, v: VAlign) -> Self { - Align { - h: h, - v: v, - } + Align { h: h, v: v } } /// Creates a top-left alignment. @@ -61,7 +58,7 @@ impl HAlign { pub fn get_offset(&self, content: usize, container: usize) -> usize { match *self { HAlign::Left => 0, - HAlign::Center => (container - content)/2, + HAlign::Center => (container - content) / 2, HAlign::Right => (container - content), } } @@ -73,7 +70,7 @@ impl VAlign { pub fn get_offset(&self, content: usize, container: usize) -> usize { match *self { VAlign::Top => 0, - VAlign::Center => (container - content)/2, + VAlign::Center => (container - content) / 2, VAlign::Bottom => (container - content), } } diff --git a/src/div.rs b/src/div.rs index 48cad6b..c6a3a4b 100644 --- a/src/div.rs +++ b/src/div.rs @@ -5,6 +5,9 @@ pub fn div_up_usize(p: usize, q: usize) -> usize { /// Integer division that rounds up. pub fn div_up(p: u32, q: u32) -> u32 { - if p % q == 0 { p/q } - else { 1 + p/q } + if p % q == 0 { + p / q + } else { + 1 + p / q + } } diff --git a/src/event.rs b/src/event.rs index a1436a6..845f846 100644 --- a/src/event.rs +++ b/src/event.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use ncurses; -use ::Cursive; +use Cursive; /// Callback is a function that can be triggered by an event. /// It has a mutable access to the cursive root. @@ -136,10 +136,10 @@ impl Key { f @ 293 ... 303 => Key::CtrlF((f - 293 + 5) as u8), f @ 305 ... 315 => Key::CtrlShiftF((f - 305 + 5) as u8), // Shift and Ctrl F{1-4} need escape sequences... - + // // TODO: shift and ctrl Fn keys // 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), } } @@ -154,49 +154,51 @@ impl fmt::Display for Key { Key::ShiftF(n) => write!(f, "Shift-F{}", n), Key::CtrlF(n) => write!(f, "Ctrl-F{}", n), Key::CtrlShiftF(n) => write!(f, "Ctrl-Shift-F{}", n), - key => write!(f, "{}", match key { - Key::NumpadCenter => "Numpad center", - Key::Left => "Left", - Key::Right => "Right", - Key::Down => "Down", - Key::Up => "Up", - Key::CtrlShiftLeft => "Ctrl-Shift-Left", - Key::CtrlShiftRight => "Ctrl-Shift-Right", - Key::CtrlShiftUp => "Ctrl-Shift-Up", - Key::CtrlShiftDown => "Ctrl-Shift-Down", - Key::ShiftUp => "Shift-Up", - Key::ShiftDown => "Shift-Down", - Key::ShiftLeft => "Shift-Left", - Key::ShiftRight => "Shift-Right", - Key::ShiftDel => "Shift-Del", - Key::CtrlDel => "Ctrl-Del", - Key::CtrlShiftDel => "Ctrl-Shift-Del", - Key::CtrlLeft => "Ctrl-Left", - Key::CtrlRight => "Ctrl-Right", - Key::CtrlUp => "Ctrl-Up", - Key::CtrlDown => "Ctrl-Down", - Key::CtrlPageUp => "Ctrl-PageUp", - Key::CtrlPageDown => "Ctrl-PageDown", - Key::PageUp => "PageUp", - Key::PageDown => "PageDown", - Key::Home => "Home", - Key::ShiftHome => "Shift-Home", - Key::CtrlHome => "Ctrl-Home", - Key::CtrlShiftHome => "Ctrl-Shift-Home", - Key::End => "End", - Key::ShiftEnd => "Shift-End", - Key::CtrlEnd => "Ctrl-End", - Key::CtrlShiftEnd => "Ctrl-Shift-End", - Key::Backspace => "Backspace", - Key::Del => "Del", - Key::Enter => "Enter", - Key::ShiftTab => "Shift-Tab", - Key::Tab => "Tab", - Key::Ins => "Ins", - Key::CtrlIns => "Ctrl-Ins", - Key::Esc => "Esc", - _ => "Missing key label", - }), + key => write!(f, + "{}", + match key { + Key::NumpadCenter => "Numpad center", + Key::Left => "Left", + Key::Right => "Right", + Key::Down => "Down", + Key::Up => "Up", + Key::CtrlShiftLeft => "Ctrl-Shift-Left", + Key::CtrlShiftRight => "Ctrl-Shift-Right", + Key::CtrlShiftUp => "Ctrl-Shift-Up", + Key::CtrlShiftDown => "Ctrl-Shift-Down", + Key::ShiftUp => "Shift-Up", + Key::ShiftDown => "Shift-Down", + Key::ShiftLeft => "Shift-Left", + Key::ShiftRight => "Shift-Right", + Key::ShiftDel => "Shift-Del", + Key::CtrlDel => "Ctrl-Del", + Key::CtrlShiftDel => "Ctrl-Shift-Del", + Key::CtrlLeft => "Ctrl-Left", + Key::CtrlRight => "Ctrl-Right", + Key::CtrlUp => "Ctrl-Up", + Key::CtrlDown => "Ctrl-Down", + Key::CtrlPageUp => "Ctrl-PageUp", + Key::CtrlPageDown => "Ctrl-PageDown", + Key::PageUp => "PageUp", + Key::PageDown => "PageDown", + Key::Home => "Home", + Key::ShiftHome => "Shift-Home", + Key::CtrlHome => "Ctrl-Home", + Key::CtrlShiftHome => "Ctrl-Shift-Home", + Key::End => "End", + Key::ShiftEnd => "Shift-End", + Key::CtrlEnd => "Ctrl-End", + Key::CtrlShiftEnd => "Ctrl-Shift-End", + Key::Backspace => "Backspace", + Key::Del => "Del", + Key::Enter => "Enter", + Key::ShiftTab => "Shift-Tab", + Key::Tab => "Tab", + Key::Ins => "Ins", + Key::CtrlIns => "Ctrl-Ins", + Key::Esc => "Esc", + _ => "Missing key label", + }), } } } diff --git a/src/lib.rs b/src/lib.rs index 6aea336..74979bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,9 +42,9 @@ use std::path::Path; use vec::Vec2; use printer::Printer; use view::View; -use view::{StackView,Selector}; +use view::{StackView, Selector}; -use event::{Event,ToEvent,Key,EventResult,Callback}; +use event::{Event, ToEvent, Key, EventResult, Callback}; /// Identifies a screen in the cursive ROOT. pub type ScreenId = usize; @@ -83,7 +83,8 @@ impl Cursive { let theme = theme::load_default(); // let theme = theme::load_theme("assets/style.toml").unwrap(); - ncurses::wbkgd(ncurses::stdscr, ncurses::COLOR_PAIR(theme::ColorPair::Background.ncurses_id())); + ncurses::wbkgd(ncurses::stdscr, + ncurses::COLOR_PAIR(theme::ColorPair::Background.ncurses_id())); let mut res = Cursive { screens: Vec::new(), @@ -148,7 +149,9 @@ impl Cursive { /// Sets the active screen. Panics if no such screen exist. pub fn set_screen(&mut self, screen_id: ScreenId) { if screen_id >= self.screens.len() { - panic!("Tried to set an invalid screen ID: {}, but only {} screens present.", screen_id, self.screens.len()); + panic!("Tried to set an invalid screen ID: {}, but only {} screens present.", + screen_id, + self.screens.len()); } self.active_screen = screen_id; } @@ -174,7 +177,7 @@ impl Cursive { } /// Adds a global callback, triggered on the given key press when no view catches it. - pub fn add_global_callback(&mut self, event: E, cb: F) + pub fn add_global_callback(&mut self, event: E, cb: F) where F: Fn(&mut Cursive) + 'static { self.global_callbacks.insert(event.to_event(), Rc::new(Box::new(cb))); @@ -275,4 +278,3 @@ impl Drop for Cursive { ncurses::endwin(); } } - diff --git a/src/orientation.rs b/src/orientation.rs index 799b7c8..29e5aed 100644 --- a/src/orientation.rs +++ b/src/orientation.rs @@ -30,7 +30,7 @@ impl Orientation { /// Returns a mutable reference to the component of the given vector /// corresponding to this orientation. - pub fn get_ref<'a,'b>(&'a self, v: &'b mut Vec2) -> &'b mut usize { + pub fn get_ref<'a, 'b>(&'a self, v: &'b mut Vec2) -> &'b mut usize { match *self { Orientation::Horizontal => &mut v.x, Orientation::Vertical => &mut v.y, @@ -42,10 +42,10 @@ impl Orientation { /// /// For an horizontal view, returns (Sum(x), Max(y)). /// For a vertical view, returns (Max(x),Sum(y)). - pub fn stack<'a,T: Iterator>(&self, iter: T) -> Vec2 { + pub fn stack<'a, T: Iterator>(&self, iter: T) -> Vec2 { match *self { - Orientation::Horizontal => iter.fold(Vec2::zero(), |a,b| a.stack_horizontal(&b)), - Orientation::Vertical => iter.fold(Vec2::zero(), |a,b| a.stack_vertical(&b)), + Orientation::Horizontal => iter.fold(Vec2::zero(), |a, b| a.stack_horizontal(&b)), + Orientation::Vertical => iter.fold(Vec2::zero(), |a, b| a.stack_vertical(&b)), } } } diff --git a/src/printer.rs b/src/printer.rs index 6ff26bb..1636e60 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -3,9 +3,10 @@ use std::cmp::min; use ncurses; +use ncurses::chtype; -use theme::{ColorPair,Theme}; -use vec::{Vec2,ToVec2}; +use theme::{ColorPair, Theme}; +use vec::{Vec2, ToVec2}; /// Convenient interface to draw on a subset of the screen. pub struct Printer { @@ -33,12 +34,14 @@ impl Printer { /// Prints some text at the given position relative to the window. pub fn print(&self, pos: S, text: &str) { let p = pos.to_vec2(); - if p.y >= self.size.y || p.x >= self.size.x { return; } + if p.y >= self.size.y || p.x >= self.size.x { + return; + } // Do we have enough room for the entire line? let room = self.size.x - p.x; // We want the number of CHARACTERS, not bytes. let text = match text.char_indices().nth(room) { - Some((i,_)) => &text[..i], + Some((i, _)) => &text[..i], _ => text, }; @@ -51,9 +54,11 @@ impl Printer { } /// Prints a vertical line using the given character. - pub fn print_vline(&self, start: T, len: usize, c: u64) { + pub fn print_vline(&self, start: T, len: usize, c: chtype) { let p = start.to_vec2(); - if p.y > self.size.y || p.x > self.size.x { return; } + if p.y > self.size.y || p.x > self.size.x { + return; + } let len = min(len, self.size.y - p.y); let p = p + self.offset; @@ -61,9 +66,11 @@ impl Printer { } /// Prints a horizontal line using the given character. - pub fn print_hline(&self, start: T, len: usize, c: u64) { + pub fn print_hline(&self, start: T, len: usize, c: chtype) { let p = start.to_vec2(); - if p.y > self.size.y || p.x > self.size.x { return; } + if p.y > self.size.y || p.x > self.size.x { + return; + } let len = min(len, self.size.x - p.x); let p = p + self.offset; @@ -114,17 +121,21 @@ impl Printer { /// ``` pub fn print_box(&self, start: T, size: T) { let start_v = start.to_vec2(); - let size_v = size.to_vec2() - (1,1); + let size_v = size.to_vec2() - (1, 1); self.print(start_v, "┌"); self.print(start_v + size_v.keep_x(), "┐"); self.print(start_v + size_v.keep_y(), "└"); self.print(start_v + size_v, "┘"); - self.print_hline(start_v + (1,0), size_v.x - 1, ncurses::ACS_HLINE()); - self.print_vline(start_v + (0,1), size_v.y - 1, ncurses::ACS_VLINE()); - self.print_hline(start_v + (1,0) + size_v.keep_y(), size_v.x - 1, ncurses::ACS_HLINE()); - self.print_vline(start_v + (0,1) + size_v.keep_x(), size_v.y - 1, ncurses::ACS_VLINE()); + self.print_hline(start_v + (1, 0), size_v.x - 1, ncurses::ACS_HLINE()); + self.print_vline(start_v + (0, 1), size_v.y - 1, ncurses::ACS_VLINE()); + self.print_hline(start_v + (1, 0) + size_v.keep_y(), + size_v.x - 1, + ncurses::ACS_HLINE()); + self.print_vline(start_v + (0, 1) + size_v.keep_x(), + size_v.y - 1, + ncurses::ACS_VLINE()); } /// Returns a printer on a subset of this one's area. diff --git a/src/theme.rs b/src/theme.rs index c7dd3b2..35c7b1e 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -100,15 +100,29 @@ impl Theme { } fn apply(&self) { - Theme::apply_color(ColorPair::Background, &self.colors.background, &self.colors.background); + Theme::apply_color(ColorPair::Background, + &self.colors.background, + &self.colors.background); Theme::apply_color(ColorPair::Shadow, &self.colors.shadow, &self.colors.shadow); Theme::apply_color(ColorPair::Primary, &self.colors.primary, &self.colors.view); - Theme::apply_color(ColorPair::Secondary, &self.colors.secondary, &self.colors.view); - Theme::apply_color(ColorPair::Tertiary, &self.colors.tertiary, &self.colors.view); - Theme::apply_color(ColorPair::TitlePrimary, &self.colors.title_primary, &self.colors.view); - Theme::apply_color(ColorPair::TitleSecondary, &self.colors.title_secondary, &self.colors.view); - Theme::apply_color(ColorPair::Highlight, &self.colors.view, &self.colors.highlight); - Theme::apply_color(ColorPair::HighlightInactive, &self.colors.view, &self.colors.highlight_inactive); + Theme::apply_color(ColorPair::Secondary, + &self.colors.secondary, + &self.colors.view); + Theme::apply_color(ColorPair::Tertiary, + &self.colors.tertiary, + &self.colors.view); + Theme::apply_color(ColorPair::TitlePrimary, + &self.colors.title_primary, + &self.colors.view); + Theme::apply_color(ColorPair::TitleSecondary, + &self.colors.title_secondary, + &self.colors.view); + Theme::apply_color(ColorPair::Highlight, + &self.colors.view, + &self.colors.highlight); + Theme::apply_color(ColorPair::HighlightInactive, + &self.colors.view, + &self.colors.highlight_inactive); } fn apply_color(pair: ColorPair, front: &Color, back: &Color) { @@ -192,12 +206,12 @@ pub struct Color { impl Color { /// Return the rgb values used by the color. - pub fn rgb(&self) -> (i16,i16,i16) { - let (mut r, mut g, mut b) = (0,0,0); + pub fn rgb(&self) -> (i16, i16, i16) { + let (mut r, mut g, mut b) = (0, 0, 0); ncurses::color_content(self.id, &mut r, &mut g, &mut b); - (r,g,b) + (r, g, b) } } @@ -244,10 +258,14 @@ impl Color { fn load(&mut self, table: &toml::Table, key: &str, new_id: &mut i16) { match table.get(key) { - Some(&toml::Value::String(ref value)) => { self.load_value(value, new_id); }, + Some(&toml::Value::String(ref value)) => { + self.load_value(value, new_id); + } Some(&toml::Value::Array(ref array)) => for color in array.iter() { match color { - &toml::Value::String(ref color) => if self.load_value(color, new_id) { return; }, + &toml::Value::String(ref color) => if self.load_value(color, new_id) { + return; + }, _ => (), } }, @@ -278,15 +296,15 @@ impl Color { } let s = &value[1..]; - let (l,max) = match s.len() { - 6 => (2,255), - 3 => (1,15), + let (l, max) = match s.len() { + 6 => (2, 255), + 3 => (1, 15), _ => panic!("Cannot parse color: {}", s), }; - let r = (load_hex(&s[0*l..1*l]) as i32 * 1000 / max) as i16; - let g = (load_hex(&s[1*l..2*l]) as i32 * 1000 / max) as i16; - let b = (load_hex(&s[2*l..3*l]) as i32 * 1000 / max) as i16; + let r = (load_hex(&s[0 * l..1 * l]) as i32 * 1000 / max) as i16; + let g = (load_hex(&s[1 * l..2 * l]) as i32 * 1000 / max) as i16; + let b = (load_hex(&s[2 * l..3 * l]) as i32 * 1000 / max) as i16; ncurses::init_color(*new_id, r, g, b); @@ -330,10 +348,10 @@ impl Color { /// /// ```text /// # Every field in a theme file is optional. -/// +/// /// shadow = false /// borders = "simple" # Alternatives are "none" and "outset" -/// +/// /// # Base colors are red, green, blue, /// # cyan, magenta, yellow, white and black. /// [colors] @@ -343,23 +361,23 @@ impl Color { /// # non-base colors will be skipped. /// shadow = ["#000000", "black"] /// view = "#d3d7cf" -/// +/// /// # Array and simple values have the same effect. /// primary = ["#111111"] /// secondary = "#EEEEEE" /// tertiary = "#444444" -/// +/// /// # Hex values can use lower or uppercase. /// # (base color MUST be lowercase) /// title_primary = "#ff5555" /// title_secondary = "#ffff55" -/// +/// /// # Lower precision values can use only 3 digits. /// highlight = "#F00" /// highlight_inactive = "#5555FF" /// ``` -pub fn load_theme>(filename: P) -> Result { +pub fn load_theme>(filename: P) -> Result { let content = { let mut content = String::new(); let mut file = try!(File::open(filename)); diff --git a/src/utf8.rs b/src/utf8.rs index 2f1e9a9..a2608cf 100644 --- a/src/utf8.rs +++ b/src/utf8.rs @@ -3,18 +3,18 @@ use std::char::from_u32; /// Reads a char from a first byte, and a function to fetch next bytes as required. /// /// Returns an error if the stream is invalid utf-8. -pub fn read_char(first: u8, next: F) -> Result +pub fn read_char(first: u8, next: F) -> Result where F: Fn() -> u8 { if first < 0x80 { - return Ok(first as char) + return Ok(first as char); } // Number of leading 1s determines the number of bytes we'll have to read let n_bytes = match (!first).leading_zeros() { n @ 2 ... 6 => n as usize, 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!(), }; diff --git a/src/vec.rs b/src/vec.rs index ebe28d6..feb72fe 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,7 +1,7 @@ //! Points on the 2D character grid. use std::ops::{Add, Sub, Mul, Div}; -use std::cmp::{min,max,Ordering}; +use std::cmp::{min, max, Ordering}; /// Simple 2D size, in characters. #[derive(Clone,Copy,PartialEq,Debug)] @@ -14,20 +14,22 @@ pub struct Vec2 { impl PartialOrd for Vec2 { fn partial_cmp(&self, other: &Vec2) -> Option { - if self == other { Some(Ordering::Equal) } - else if self.x < other.x && self.y < other.y { Some(Ordering::Less) } - else if self.x > other.x && self.y > other.y { Some(Ordering::Greater) } - else { None } + if self == other { + Some(Ordering::Equal) + } else if self.x < other.x && self.y < other.y { + Some(Ordering::Less) + } else if self.x > other.x && self.y > other.y { + Some(Ordering::Greater) + } else { + None + } } } impl Vec2 { /// Creates a new Vec2 from coordinates. pub fn new(x: usize, y: usize) -> Self { - Vec2 { - x: x, - y: y, - } + Vec2 { x: x, y: y } } /// Returns a new Vec2 that is a maximum per coordinate. @@ -52,7 +54,7 @@ impl Vec2 { /// Alias for Vec::new(0,0). pub fn zero() -> Self { - Vec2::new(0,0) + Vec2::new(0, 0) } /// Returns (max(self.x,other.x), self.y+other.y) @@ -199,7 +201,9 @@ pub trait ToVec4 { } impl ToVec4 for Vec4 { - fn to_vec4(self) -> Vec4 { self } + fn to_vec4(self) -> Vec4 { + self + } } impl ToVec4 for (usize,usize,usize,usize) { @@ -210,7 +214,10 @@ impl ToVec4 for (usize,usize,usize,usize) { impl ToVec4 for (i32,i32,i32,i32) { fn to_vec4(self) -> Vec4 { - Vec4::new(self.0 as usize, self.1 as usize, self.2 as usize, self.3 as usize) + Vec4::new(self.0 as usize, + self.1 as usize, + self.2 as usize, + self.3 as usize) } } @@ -270,4 +277,3 @@ impl Mul for Vec4 { } } } - diff --git a/src/view/box_view.rs b/src/view/box_view.rs index 6235459..1beb2a0 100644 --- a/src/view/box_view.rs +++ b/src/view/box_view.rs @@ -1,5 +1,5 @@ -use vec::{Vec2,ToVec2}; -use super::{View,ViewWrapper,SizeRequest,DimensionRequest}; +use vec::{Vec2, ToVec2}; +use super::{View, ViewWrapper, SizeRequest, DimensionRequest}; /// BoxView is a wrapper around an other view, with a given minimum size. pub struct BoxView { @@ -30,13 +30,21 @@ impl ViewWrapper for BoxView { wrap_impl!(&self.view); fn wrap_get_min_size(&self, mut req: SizeRequest) -> Vec2 { - if self.size.x > 0 { req.w = DimensionRequest::AtMost(self.size.x); } - if self.size.y > 0 { req.h = DimensionRequest::AtMost(self.size.y); } + if self.size.x > 0 { + req.w = DimensionRequest::AtMost(self.size.x); + } + if self.size.y > 0 { + req.h = DimensionRequest::AtMost(self.size.y); + } let mut size = self.view.get_min_size(req); - if self.size.x > 0 { size.x = self.size.x; } - if self.size.y > 0 { size.y = self.size.y; } + if self.size.x > 0 { + size.x = self.size.x; + } + if self.size.y > 0 { + size.y = self.size.y; + } size } diff --git a/src/view/button.rs b/src/view/button.rs index 8fb3b2e..806bcab 100644 --- a/src/view/button.rs +++ b/src/view/button.rs @@ -1,9 +1,9 @@ use std::rc::Rc; use theme::ColorPair; -use ::Cursive; +use Cursive; use vec::Vec2; -use view::{View,SizeRequest}; +use view::{View, SizeRequest}; use event::*; use printer::Printer; @@ -29,13 +29,17 @@ impl Button { impl View for Button { fn draw(&mut self, printer: &Printer) { - let style = if !printer.focused { ColorPair::Primary } else { ColorPair::Highlight }; + let style = if !printer.focused { + ColorPair::Primary + } else { + ColorPair::Highlight + }; let x = printer.size.x - 1; printer.with_color(style, |printer| { - printer.print((1,0), &self.label); - printer.print((0,0), "<"); - printer.print((x,0), ">"); + printer.print((1, 0), &self.label); + printer.print((0, 0), "<"); + printer.print((x, 0), ">"); }); } diff --git a/src/view/dialog.rs b/src/view/dialog.rs index 03d016e..3ca5989 100644 --- a/src/view/dialog.rs +++ b/src/view/dialog.rs @@ -1,13 +1,13 @@ use std::cmp::max; use std::any::Any; -use ::{Cursive}; +use Cursive; use align::*; use event::*; use theme::ColorPair; -use view::{View,SizeRequest,DimensionRequest,Selector}; -use view::{Button,SizedView}; -use vec::{Vec2,Vec4,ToVec4}; +use view::{View, SizeRequest, DimensionRequest, Selector}; +use view::{Button, SizedView}; +use vec::{Vec2, Vec4, ToVec4}; use printer::Printer; #[derive(PartialEq)] @@ -46,8 +46,8 @@ impl Dialog { buttons: Vec::new(), title: String::new(), focus: Focus::Content, - padding: Vec4::new(1,1,0,0), - borders: Vec4::new(1,1,1,1), + padding: Vec4::new(1, 1, 0, 0), + borders: Vec4::new(1, 1, 1, 1), align: Align::top_right(), } } @@ -111,59 +111,55 @@ impl View for Dialog { let width = if self.buttons.is_empty() { 0 } else { - self.buttons.iter() + self.buttons + .iter() .map(|button| button.size.x) - .fold(0, |a,b| a+b) + - self.buttons.len() - 1 + .fold(0, |a, b| a + b) + self.buttons.len() - 1 }; let overhead = self.padding + self.borders; let mut offset = overhead.left + - self.align.h.get_offset(width, printer.size.x - - overhead.horizontal()); + self.align.h.get_offset(width, printer.size.x - overhead.horizontal()); let y = printer.size.y - self.padding.bottom - self.borders.bottom - 1; - for (i,button) in self.buttons.iter_mut().enumerate() { + for (i, button) in self.buttons.iter_mut().enumerate() { let size = button.size; // Add some special effect to the focused button - button.draw(&printer.sub_printer(Vec2::new(offset, y), size, self.focus == Focus::Button(i))); + button.draw(&printer.sub_printer(Vec2::new(offset, y), + size, + self.focus == Focus::Button(i))); // Keep 1 blank between two buttons offset += size.x + 1; // Also keep 1 blank above the buttons - height = max(height, size.y+1); + height = max(height, size.y + 1); } // What do we have left? - let inner_size = printer.size - - Vec2::new(0, height) - - self.borders.combined() - - self.padding.combined(); + let inner_size = printer.size - Vec2::new(0, height) - self.borders.combined() - + self.padding.combined(); - self.content.draw(&printer.sub_printer(self.borders.top_left() + - self.padding.top_left(), + self.content.draw(&printer.sub_printer(self.borders.top_left() + self.padding.top_left(), inner_size, self.focus == Focus::Content)); - printer.print_box(Vec2::new(0,0), printer.size); + printer.print_box(Vec2::new(0, 0), printer.size); if self.title.len() > 0 { let len = self.title.chars().count(); let x = (printer.size.x - len) / 2; - printer.print((x-2,0), "┤ "); - printer.print((x+len,0), " ├"); + printer.print((x - 2, 0), "┤ "); + printer.print((x + len, 0), " ├"); - printer.with_color(ColorPair::TitlePrimary, - |p| p.print((x,0), &self.title)); + printer.with_color(ColorPair::TitlePrimary, |p| p.print((x, 0), &self.title)); } } fn get_min_size(&self, req: SizeRequest) -> Vec2 { // Padding and borders are not available for kids. - let content_req = req.reduced(self.padding.combined() + - self.borders.combined()); + let content_req = req.reduced(self.padding.combined() + self.borders.combined()); let content_size = self.content.get_min_size(content_req); - let mut buttons_size = Vec2::new(0,0); + let mut buttons_size = Vec2::new(0, 0); if !self.buttons.is_empty() { buttons_size.x += self.buttons.len() - 1; } @@ -176,8 +172,9 @@ impl View for Dialog { // On the Y axis, we add buttons and content. // On the X axis, we take the max. let mut inner_size = Vec2::new(max(content_size.x, buttons_size.x), - content_size.y + buttons_size.y) - + self.padding.combined() + self.borders.combined(); + content_size.y + buttons_size.y) + + self.padding.combined() + + self.borders.combined(); if self.title.len() > 0 { // If we have a title, we have to fit it too! @@ -199,7 +196,7 @@ impl View for Dialog { let mut buttons_height = 0; for button in self.buttons.iter_mut().rev() { let size = button.get_min_size(req); - buttons_height = max(buttons_height, size.y+1); + buttons_height = max(buttons_height, size.y + 1); button.layout(size); } @@ -216,7 +213,7 @@ impl View for Dialog { // 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) @@ -236,7 +233,7 @@ impl View for Dialog { } else { EventResult::Ignored } - }, + } Event::KeyEvent(Key::Tab) | Event::KeyEvent(Key::ShiftTab) => { if self.content.take_focus() { self.focus = Focus::Content; @@ -244,16 +241,16 @@ impl View for Dialog { } 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); + 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); + self.focus = Focus::Button(i - 1); EventResult::Consumed(None) - }, + } _ => EventResult::Ignored, }, res => res, diff --git a/src/view/edit_view.rs b/src/view/edit_view.rs index 4f0ec11..61345f9 100644 --- a/src/view/edit_view.rs +++ b/src/view/edit_view.rs @@ -1,10 +1,10 @@ -use ncurses; +use ncurses::{self, chtype}; use std::cmp::min; use theme::ColorPair; use vec::Vec2; -use view::{View,IdView,SizeRequest}; +use view::{View, IdView, SizeRequest}; use event::*; use printer::Printer; @@ -20,9 +20,8 @@ pub struct EditView { /// When the content is too long for the display, offset it offset: usize, /// Last display length, to know the possible offset range - last_length: usize, - // scrollable: bool, - // TODO: add a max text length? + last_length: usize, /* scrollable: bool, + * TODO: add a max text length? */ } impl EditView { @@ -33,8 +32,7 @@ impl EditView { cursor: 0, offset: 0, min_length: 1, - last_length: 0, - // scrollable: false, + last_length: 0, /* scrollable: false, */ } } @@ -71,7 +69,7 @@ impl EditView { fn remove_char(s: &mut String, cursor: usize) { let i = match s.char_indices().nth(cursor) { - Some((i,_)) => i, + Some((i, _)) => i, None => return, }; s.remove(i); @@ -84,15 +82,15 @@ impl View for EditView { printer.with_color(ColorPair::Secondary, |printer| { printer.with_style(ncurses::A_REVERSE(), |printer| { if len < self.last_length { - printer.print((0,0), &self.content); - printer.print_hline((len,0), printer.size.x-len, '_' as u64); + printer.print((0, 0), &self.content); + printer.print_hline((len, 0), printer.size.x - len, '_' as chtype); } else { let visible_end = min(self.content.len(), self.offset + self.last_length); let content = &self.content[self.offset..visible_end]; - printer.print((0,0), content); + printer.print((0, 0), content); if visible_end - self.offset < printer.size.x { - printer.print((printer.size.x-1,0), "_"); + printer.print((printer.size.x - 1, 0), "_"); } } }); @@ -103,9 +101,14 @@ impl View for EditView { '_' } else { // Get the char from the string... Is it so hard? - self.content.chars().nth(self.cursor).expect(&format!("Found no char at cursor {} in {}", self.cursor, self.content)) + self.content + .chars() + .nth(self.cursor) + .expect(&format!("Found no char at cursor {} in {}", + self.cursor, + self.content)) }; - printer.print_hline((self.cursor-self.offset, 0), 1, c as u64); + printer.print_hline((self.cursor - self.offset, 0), 1, c as chtype); } }); } @@ -130,18 +133,23 @@ impl View for EditView { match self.content.char_indices().nth(self.cursor) { None => self.content.push(ch), - Some((i,_)) => self.content.insert(i, ch), + Some((i, _)) => self.content.insert(i, ch), } // TODO: handle wide (CJK) chars self.cursor += 1; - }, + } Event::KeyEvent(key) => match key { Key::Home => self.cursor = 0, Key::End => self.cursor = self.content.chars().count(), Key::Left if self.cursor > 0 => self.cursor -= 1, Key::Right if self.cursor < self.content.chars().count() => self.cursor += 1, - Key::Backspace if self.cursor > 0 => { 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); }, + Key::Backspace if self.cursor > 0 => { + 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, }, } @@ -154,8 +162,8 @@ impl View for EditView { } else if self.cursor < self.offset { self.offset = self.cursor; } - if self.offset + self.last_length > self.content.len() + 1{ - + if self.offset + self.last_length > self.content.len() + 1 { + self.offset = if self.content.len() > self.last_length { self.content.len() - self.last_length + 1 } else { diff --git a/src/view/full_view.rs b/src/view/full_view.rs index abee21d..8069a28 100644 --- a/src/view/full_view.rs +++ b/src/view/full_view.rs @@ -1,4 +1,4 @@ -use view::{View,ViewWrapper,SizeRequest,DimensionRequest}; +use view::{View, ViewWrapper, SizeRequest, DimensionRequest}; use vec::Vec2; /// Simple wrapper view that asks for all the space it can get. @@ -9,9 +9,7 @@ pub struct FullView { impl FullView { /// Wraps the given view into a new FullView. pub fn new(view: T) -> Self { - FullView { - view: view, - } + FullView { view: view } } } @@ -30,6 +28,6 @@ impl ViewWrapper for FullView { DimensionRequest::Unknown => self.view.get_min_size(req).y, }; - Vec2::new(w,h) + Vec2::new(w, h) } } diff --git a/src/view/id_view.rs b/src/view/id_view.rs index d632f7a..eb8baa9 100644 --- a/src/view/id_view.rs +++ b/src/view/id_view.rs @@ -1,6 +1,6 @@ use std::any::Any; -use view::{View,ViewWrapper,Selector}; +use view::{View, ViewWrapper, Selector}; /// Wrapper view that allows to select its content with a fixed string id. pub struct IdView { diff --git a/src/view/key_event_view.rs b/src/view/key_event_view.rs index 265106b..9054ba5 100644 --- a/src/view/key_event_view.rs +++ b/src/view/key_event_view.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; use std::rc::Rc; -use ::Cursive; -use event::{Event,EventResult,ToEvent,Callback}; -use super::{View,ViewWrapper}; +use Cursive; +use event::{Event, EventResult, ToEvent, Callback}; +use super::{View, ViewWrapper}; /// A simple wrapper view that catches some ignored event from its child. /// @@ -23,7 +23,7 @@ impl KeyEventView { } /// Registers a callback when the given key is ignored by the child. - pub fn register(mut self, event: E, cb: F) -> Self + pub fn register(mut self, event: E, cb: F) -> Self where F: Fn(&mut Cursive) + 'static { self.callbacks.insert(event.to_event(), Rc::new(Box::new(cb))); diff --git a/src/view/linear_layout.rs b/src/view/linear_layout.rs index f587918..099a7fd 100644 --- a/src/view/linear_layout.rs +++ b/src/view/linear_layout.rs @@ -1,8 +1,8 @@ -use view::{View,SizeRequest,DimensionRequest}; +use view::{View, SizeRequest, DimensionRequest}; use vec::Vec2; use printer::Printer; use orientation::Orientation; -use event::{Event,EventResult,Key}; +use event::{Event, EventResult, Key}; /// Arranges its children linearly according to its orientation. pub struct LinearLayout { @@ -63,7 +63,7 @@ impl LinearLayout { fn find_max(list: &Vec) -> usize { let mut max_value = 0; let mut max = 0; - for (i,&x) in list.iter().enumerate() { + for (i, &x) in list.iter().enumerate() { if x > max_value { max_value = x; max = i; @@ -78,9 +78,11 @@ fn find_max(list: &Vec) -> usize { fn share(total: usize, weights: Vec) -> Vec { // It first give a base value to everyone, which is their truncated share. // Then, it gives the rest to the most deserving. - if weights.len() == 0 { return Vec::new(); } + if weights.len() == 0 { + return Vec::new(); + } - let sum_weight = weights.iter().fold(0,|a,b| a+b); + let sum_weight = weights.iter().fold(0, |a, b| a + b); if sum_weight == 0 { return (0..weights.len()).map(|_| 0).collect(); } @@ -93,7 +95,7 @@ fn share(total: usize, weights: Vec) -> Vec { let b = total * weight / sum_weight; extra -= b; base.push(b); - rest.push(total * weight - b*sum_weight); + rest.push(total * weight - b * sum_weight); } // TODO: better to sort (base,rest) as one array and pick the extra first. @@ -110,7 +112,7 @@ impl View for LinearLayout { fn draw(&mut self, printer: &Printer) { // Use pre-computed sizes let mut offset = Vec2::zero(); - for (i,child) in self.children.iter_mut().enumerate() { + for (i, child) in self.children.iter_mut().enumerate() { child.view.draw(&printer.sub_printer(offset, child.size, i == self.focus)); *self.orientation.get_ref(&mut offset) += self.orientation.get(&child.size); @@ -119,18 +121,21 @@ impl View for LinearLayout { fn layout(&mut self, size: Vec2) { // Compute the very minimal required size - let req = SizeRequest{ + let req = SizeRequest { w: DimensionRequest::AtMost(size.x), h: DimensionRequest::AtMost(size.y), }; - let min_sizes: Vec = self.children.iter().map(|child| child.view.get_min_size(req)).collect(); + let min_sizes: Vec = self.children + .iter() + .map(|child| child.view.get_min_size(req)) + .collect(); let min_size = self.orientation.stack(min_sizes.iter()); // Emulate 'non-strict inequality' on integers // (default comparison on Vec2 is strict) - if !(min_size < size+(1,1)) { + if !(min_size < size + (1, 1)) { // Error! Not enough space! Emergency procedures! - return + return; } // Now share this extra space among everyone @@ -138,11 +143,14 @@ impl View for LinearLayout { let extras = { let extra = size - min_size; let space = self.orientation.get(&extra); - share(space, self.children.iter().map(|child| child.weight).collect()) + share(space, + self.children.iter().map(|child| child.weight).collect()) }; - for (child,(child_size,extra)) in self.children.iter_mut().zip(min_sizes.iter().zip(extras.iter())) { + for (child, (child_size, extra)) in self.children + .iter_mut() + .zip(min_sizes.iter().zip(extras.iter())) { let mut child_size = *child_size; *self.orientation.get_ref(&mut child_size) += *extra; *self.orientation.swap().get_ref(&mut child_size) = self.orientation.swap().get(&size); @@ -153,7 +161,10 @@ impl View for LinearLayout { fn get_min_size(&self, req: SizeRequest) -> Vec2 { // First, make a naive scenario: everything will work fine. - let sizes: Vec = self.children.iter().map(|view| view.view.get_min_size(req)).collect(); + let sizes: Vec = self.children + .iter() + .map(|view| view.view.get_min_size(req)) + .collect(); self.orientation.stack(sizes.iter()) @@ -173,27 +184,31 @@ impl View for LinearLayout { Event::KeyEvent(Key::Tab) if self.focus > 0 => { self.focus -= 1; EventResult::Consumed(None) - }, - Event::KeyEvent(Key::ShiftTab) if self.focus+1 < self.children.len() => { + } + 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 => { + 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 => { + } + 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() => { + } + 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() => { + } + 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, diff --git a/src/view/mod.rs b/src/view/mod.rs index 4221b80..c3d1dc8 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -1,6 +1,6 @@ //! Defines various views to use when creating the layout. -#[macro_use] mod view_wrapper; +#[macro_use]mod view_wrapper; mod box_view; mod button; @@ -22,11 +22,11 @@ mod view_path; use std::any::Any; -use event::{Event,EventResult}; +use event::{Event, EventResult}; use vec::Vec2; use printer::Printer; -pub use self::request::{DimensionRequest,SizeRequest}; +pub use self::request::{DimensionRequest, SizeRequest}; pub use self::scroll::ScrollBase; pub use self::id_view::IdView; @@ -49,24 +49,33 @@ pub use self::view_wrapper::ViewWrapper; /// Main trait defining a view behaviour. pub trait View { /// Called when a key was pressed. Default implementation just ignores it. - fn on_event(&mut self, Event) -> EventResult { EventResult::Ignored } + fn on_event(&mut self, Event) -> EventResult { + EventResult::Ignored + } /// Returns the minimum size the view requires under the given restrictions. - fn get_min_size(&self, SizeRequest) -> Vec2 { Vec2::new(1,1) } + fn get_min_size(&self, SizeRequest) -> Vec2 { + Vec2::new(1, 1) + } /// Called once the size for this view has been decided, so it can /// propagate the information to its children. - fn layout(&mut self, Vec2) { } + fn layout(&mut self, Vec2) { + } /// Draws the view with the given printer (includes bounds) and focus. fn draw(&mut self, printer: &Printer); /// Finds the view pointed to by the given path. /// Returns None if the path doesn't lead to a view. - fn find(&mut self, &Selector) -> Option<&mut Any> { None } + fn find(&mut self, &Selector) -> Option<&mut Any> { + None + } /// This view is offered focus. Will it take it? - fn take_focus(&mut self) -> bool { false } + fn take_focus(&mut self) -> bool { + false + } } /// Selects a single view (if any) in the tree. @@ -76,4 +85,3 @@ pub enum Selector<'a> { /// Selects a view from its path Path(&'a ViewPath), } - diff --git a/src/view/request.rs b/src/view/request.rs index e5a02d4..c30a74d 100644 --- a/src/view/request.rs +++ b/src/view/request.rs @@ -49,5 +49,3 @@ impl SizeRequest { } } } - - diff --git a/src/view/scroll.rs b/src/view/scroll.rs index 9360505..8f39027 100644 --- a/src/view/scroll.rs +++ b/src/view/scroll.rs @@ -1,4 +1,5 @@ -use std::cmp::{min,max}; +use std::cmp::{min, max}; +use ncurses::chtype; use theme::ColorPair; use vec::Vec2; @@ -68,7 +69,7 @@ impl ScrollBase { /// Scroll down by the given number of line, never going further than the bottom of the view. pub fn scroll_down(&mut self, n: usize) { - self.start_line = min(self.start_line+n, self.content_height - self.view_height); + self.start_line = min(self.start_line + n, self.content_height - self.view_height); } /// Scroll up by the given number of lines, never going above the top of the view. @@ -98,15 +99,20 @@ impl ScrollBase { /// }); /// ``` pub fn draw(&self, printer: &Printer, line_drawer: F) - where F: Fn(&Printer,usize) + where F: Fn(&Printer, usize) { // Print the content in a sub_printer let max_y = min(self.view_height, self.content_height - self.start_line); - let w = if self.scrollable() { printer.size.x - 2 } else { printer.size.x }; + let w = if self.scrollable() { + printer.size.x - 2 + } else { + printer.size.x + }; for y in 0..max_y { // Y is the actual coordinate of the line. // The item ID is then Y + self.start_line - line_drawer(&printer.sub_printer(Vec2::new(0,y),Vec2::new(w,1),true), y+self.start_line); + line_drawer(&printer.sub_printer(Vec2::new(0, y), Vec2::new(w, 1), true), + y + self.start_line); } @@ -115,18 +121,22 @@ impl ScrollBase { // We directly compute the size of the scrollbar (this allow use to avoid using floats). // (ratio) * max_height // Where ratio is ({start or end} / content.height) - let height = max(1,self.view_height * self.view_height / self.content_height); + let height = max(1, self.view_height * self.view_height / self.content_height); // Number of different possible positions let steps = self.view_height - height + 1; // Now let start = steps * self.start_line / (1 + self.content_height - self.view_height); - let color = if printer.focused { ColorPair::Highlight } else { ColorPair::HighlightInactive }; + let color = if printer.focused { + ColorPair::Highlight + } else { + ColorPair::HighlightInactive + }; - printer.print_vline((printer.size.x-1,0), printer.size.y, '|' as u64); + printer.print_vline((printer.size.x - 1, 0), printer.size.y, '|' as chtype); printer.with_color(color, |printer| { - printer.print_vline((printer.size.x-1, start), height, ' ' as u64); + printer.print_vline((printer.size.x - 1, start), height, ' ' as chtype); }); } } diff --git a/src/view/select_view.rs b/src/view/select_view.rs index 7c413cf..c08d373 100644 --- a/src/view/select_view.rs +++ b/src/view/select_view.rs @@ -1,11 +1,12 @@ use std::cmp::min; use std::rc::Rc; +use ncurses::chtype; use theme::ColorPair; -use ::Cursive; +use Cursive; use align::*; -use view::{View,IdView,SizeRequest,DimensionRequest}; -use event::{Event,EventResult,Key}; +use view::{View, IdView, SizeRequest, DimensionRequest}; +use event::{Event, EventResult, Key}; use vec::Vec2; use printer::Printer; use super::scroll::ScrollBase; @@ -27,11 +28,11 @@ impl Item { /// View to select an item among a list. /// /// It contains a list of values of type T, with associated labels. -pub struct SelectView { +pub struct SelectView { items: Vec>, focus: usize, scrollbase: ScrollBase, - select_cb: Option>>, + select_cb: Option>>, align: Align, } @@ -91,7 +92,7 @@ impl SelectView { /// Adds a item to the list, with given label and value. pub fn add_item(&mut self, label: &str, value: T) { - self.items.push(Item::new(label,value)); + self.items.push(Item::new(label, value)); } /// Chainable variant of add_item @@ -125,21 +126,24 @@ impl View for SelectView { let h = self.items.len(); let offset = self.align.v.get_offset(h, printer.size.y); - let printer = &printer.sub_printer(Vec2::new(0,offset), printer.size, true); + let printer = &printer.sub_printer(Vec2::new(0, offset), printer.size, true); - self.scrollbase.draw(printer, |printer,i| { + self.scrollbase.draw(printer, |printer, i| { let style = if i == self.focus { - if printer.focused { ColorPair::Highlight } - else { ColorPair::HighlightInactive } + if printer.focused { + ColorPair::Highlight + } else { + ColorPair::HighlightInactive + } } else { ColorPair::Primary }; printer.with_color(style, |printer| { let l = self.items[i].label.chars().count(); let x = self.align.h.get_offset(l, printer.size.x); - printer.print_hline((0,0), x, ' ' as u64); - printer.print((x,0), &self.items[i].label); - printer.print_hline((x+l,0), printer.size.x-l-x, ' ' as u64); + printer.print_hline((0, 0), x, ' ' as chtype); + printer.print((x, 0), &self.items[i].label); + printer.print_hline((x + l, 0), printer.size.x - l - x, ' ' as chtype); }); }); } @@ -157,39 +161,43 @@ impl View for SelectView { }; // Add 2 spaces for the scrollbar if we need - let w = if scrolling { w + 2 } else { w }; + let w = if scrolling { + w + 2 + } else { + w + }; - Vec2::new(w,h) + Vec2::new(w, h) } fn on_event(&mut self, event: Event) -> EventResult { match event { 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::PageUp) => self.focus -= min(self.focus,10), - Event::KeyEvent(Key::PageDown) => self.focus = min(self.focus+10,self.items.len()-1), + Event::KeyEvent(Key::PageUp) => self.focus -= min(self.focus, 10), + Event::KeyEvent(Key::PageDown) => + self.focus = min(self.focus + 10, self.items.len() - 1), 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() => { if let Some(ref cb) = self.select_cb { let cb = cb.clone(); let v = self.selection(); return EventResult::Consumed(Some(Rc::new(Box::new(move |s| cb(s, &*v))))); } - }, + } Event::CharEvent(c) => { // Starting from the current focus, find the first item that match the char. // Cycle back to the beginning of the list when we reach the end. // This is achieved by chaining twice the iterator let iter = self.items.iter().chain(self.items.iter()); - if let Some((i,_)) = iter.enumerate() - .skip(self.focus+1) - .find(|&(_,item)| item.label.starts_with(c)) - { + if let Some((i, _)) = iter.enumerate() + .skip(self.focus + 1) + .find(|&(_, item)| item.label.starts_with(c)) { // Apply modulo in case we have a hit from the chained iterator self.focus = i % self.items.len(); } - }, + } _ => return EventResult::Ignored, } diff --git a/src/view/shadow_view.rs b/src/view/shadow_view.rs index 35b099a..99bdc58 100644 --- a/src/view/shadow_view.rs +++ b/src/view/shadow_view.rs @@ -1,4 +1,5 @@ -use view::{View,ViewWrapper,SizeRequest}; +use ncurses::chtype; +use view::{View, ViewWrapper, SizeRequest}; use printer::Printer; use vec::Vec2; use theme::ColorPair; @@ -13,9 +14,7 @@ pub struct ShadowView { impl ShadowView { /// Wraps the given view. pub fn new(view: T) -> Self { - ShadowView { - view: view, - } + ShadowView { view: view } } } @@ -24,32 +23,30 @@ impl ViewWrapper for ShadowView { wrap_impl!(&self.view); fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 { - self.view.get_min_size(req.reduced((2,2))) + (2,2) + self.view.get_min_size(req.reduced((2, 2))) + (2, 2) } fn wrap_layout(&mut self, size: Vec2) { - self.view.layout(size - (2,2)); + self.view.layout(size - (2, 2)); } fn wrap_draw(&mut self, printer: &Printer) { printer.with_color(ColorPair::Primary, |printer| { // Draw the view background - for y in 1..printer.size.y-1 { - printer.print_hline((1,y), printer.size.x-2, ' ' as u64); + for y in 1..printer.size.y - 1 { + printer.print_hline((1, y), printer.size.x - 2, ' ' as chtype); } }); - self.view.draw(&printer.sub_printer(Vec2::new(1,1), - printer.size - (2,2), - true)); + self.view.draw(&printer.sub_printer(Vec2::new(1, 1), printer.size - (2, 2), true)); - let h = printer.size.y-1; - let w = printer.size.x-1; + let h = printer.size.y - 1; + let w = printer.size.x - 1; printer.with_color(ColorPair::Shadow, |printer| { - printer.print_hline((2,h), w-1, ' ' as u64); - printer.print_vline((w,2), h-1, ' ' as u64); + printer.print_hline((2, h), w - 1, ' ' as chtype); + printer.print_vline((w, 2), h - 1, ' ' as chtype); }); } } diff --git a/src/view/sized_view.rs b/src/view/sized_view.rs index d7ccdc3..550603b 100644 --- a/src/view/sized_view.rs +++ b/src/view/sized_view.rs @@ -3,7 +3,7 @@ use vec::Vec2; use view::ViewWrapper; /// Wrapper around a view that remembers its size. -pub struct SizedView { +pub struct SizedView { /// Wrapped view. pub view: T, /// Cached size from the last layout() call. diff --git a/src/view/stack_view.rs b/src/view/stack_view.rs index 3ddc61e..46486d8 100644 --- a/src/view/stack_view.rs +++ b/src/view/stack_view.rs @@ -1,9 +1,8 @@ -use std::cmp::max; use std::any::Any; use vec::Vec2; -use view::{View,SizeRequest,DimensionRequest,Selector,ShadowView}; -use event::{Event,EventResult}; +use view::{View, SizeRequest, DimensionRequest, Selector, ShadowView}; +use event::{Event, EventResult}; use printer::Printer; /// Simple stack of views. @@ -22,16 +21,14 @@ struct Layer { impl StackView { /// Creates a new empty StackView pub fn new() -> Self { - StackView { - layers: Vec::new(), - } + StackView { layers: Vec::new() } } /// Add new view on top of the stack. pub fn add_layer(&mut self, view: T) { self.layers.push(Layer { view: Box::new(ShadowView::new(view)), - size: Vec2::new(0,0), + size: Vec2::new(0, 0), virgin: true, }); } @@ -45,12 +42,12 @@ impl StackView { impl View for StackView { fn draw(&mut self, printer: &Printer) { let last = self.layers.len(); - for (i,v) in self.layers.iter_mut().enumerate() { + for (i, v) in self.layers.iter_mut().enumerate() { // Center the view let size = v.size; let offset = (printer.size - size) / 2; // TODO: only draw focus for the top view - v.view.draw(&printer.sub_printer(offset, size, i+1 == last)); + v.view.draw(&printer.sub_printer(offset, size, i + 1 == last)); } } @@ -78,7 +75,7 @@ impl View for StackView { fn get_min_size(&self, size: SizeRequest) -> Vec2 { // The min size is the max of all children's - let mut s = Vec2::new(1,1); + let mut s = Vec2::new(1, 1); for layer in self.layers.iter() { let vs = layer.view.get_min_size(size); @@ -91,7 +88,7 @@ impl View for StackView { fn take_focus(&mut self) -> bool { match self.layers.last_mut() { None => false, - Some(mut v) => v.view.take_focus() + Some(mut v) => v.view.take_focus(), } } diff --git a/src/view/text_view.rs b/src/view/text_view.rs index 935de86..0356d2a 100644 --- a/src/view/text_view.rs +++ b/src/view/text_view.rs @@ -1,7 +1,7 @@ use std::cmp::max; use vec::Vec2; -use view::{View,DimensionRequest,SizeRequest}; +use view::{View, DimensionRequest, SizeRequest}; use div::*; use printer::Printer; use align::*; @@ -98,7 +98,8 @@ impl TextView { /// Returns the number of lines required to display the content /// with the given width. fn get_num_lines(&self, max_width: usize) -> usize { - self.content.split("\n") + self.content + .split("\n") .map(|line| get_line_span(line, max_width)) .fold(0, |sum, x| sum + x) } @@ -161,7 +162,7 @@ impl <'a> Iterator for LinesIterator<'a> { if content[..next].chars().count() <= self.width { // We found a newline before the allowed limit. // Break early. - self.start += next+1; + self.start += next + 1; return Some(Row { start: start, end: next + start, @@ -173,22 +174,22 @@ impl <'a> Iterator for LinesIterator<'a> { if content_len <= self.width { // I thought it would be longer! -- that's what she said :( self.start += content.len(); - return Some(Row{ + return Some(Row { start: start, end: start + content.len(), }); } - let i = if content_len == self.width+1 { + let i = if content_len == self.width + 1 { // We can't look at the index if we're looking at the end of the string content.len() } else { - content.char_indices().nth(self.width+1).unwrap().0 + content.char_indices().nth(self.width + 1).unwrap().0 }; let substr = &content[..i]; if let Some(i) = substr.rfind(" ") { // If we have to break, try to find a whitespace for that. - self.start += i+1; + self.start += i + 1; return Some(Row { start: start, end: i + start, @@ -210,14 +211,14 @@ impl View for TextView { let h = self.rows.len(); let offset = self.align.v.get_offset(h, printer.size.y); - let printer = &printer.sub_printer(Vec2::new(0,offset), printer.size, true); + let printer = &printer.sub_printer(Vec2::new(0, offset), printer.size, true); self.scrollbase.draw(printer, |printer, i| { let row = &self.rows[i]; let text = &self.content[row.start..row.end]; let l = text.chars().count(); let x = self.align.h.get_offset(l, printer.size.x); - printer.print((x,0), text); + printer.print((x, 0), text); }); } @@ -229,8 +230,10 @@ impl View for TextView { match event { Event::KeyEvent(Key::Home) => self.scrollbase.scroll_top(), Event::KeyEvent(Key::End) => self.scrollbase.scroll_bottom(), - Event::KeyEvent(Key::Up) if self.scrollbase.can_scroll_up() => self.scrollbase.scroll_up(1), - Event::KeyEvent(Key::Down) if self.scrollbase.can_scroll_down() => self.scrollbase.scroll_down(1), + Event::KeyEvent(Key::Up) if self.scrollbase.can_scroll_up() => + self.scrollbase.scroll_up(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::PageUp) => self.scrollbase.scroll_up(10), _ => return EventResult::Ignored, @@ -240,19 +243,19 @@ impl View for TextView { } fn get_min_size(&self, size: SizeRequest) -> Vec2 { - match (size.w,size.h) { + match (size.w, size.h) { // If we have no directive, ask for a single big line. // TODO: what if the text has newlines?? (DimensionRequest::Unknown, DimensionRequest::Unknown) => self.get_ideal_size(), - (DimensionRequest::Fixed(w),_) => { + (DimensionRequest::Fixed(w), _) => { let h = self.get_num_lines(w); Vec2::new(w, h) - }, - (_,DimensionRequest::Fixed(h)) => { + } + (_, DimensionRequest::Fixed(h)) => { let w = self.get_num_cols(h); Vec2::new(w, h) - }, - (DimensionRequest::AtMost(w),_) => { + } + (DimensionRequest::AtMost(w), _) => { // Don't _force_ the max width, but take it if we have to. let ideal = self.get_ideal_size(); @@ -262,7 +265,7 @@ impl View for TextView { let h = self.get_num_lines(w); Vec2::new(w, h) } - }, + } _ => unreachable!(), } } diff --git a/src/view/view_path.rs b/src/view/view_path.rs index bdb670a..7e21bfd 100644 --- a/src/view/view_path.rs +++ b/src/view/view_path.rs @@ -8,9 +8,7 @@ pub struct ViewPath { impl ViewPath { /// Creates a new empty path. pub fn new() -> Self { - ViewPath { - path: Vec::new(), - } + ViewPath { path: Vec::new() } } /// Creates a path from the given item. @@ -27,8 +25,6 @@ pub trait ToPath { impl <'a> ToPath for &'a [usize] { fn to_path(self) -> ViewPath { - ViewPath { - path: self.to_owned(), - } + ViewPath { path: self.to_owned() } } } diff --git a/src/view/view_wrapper.rs b/src/view/view_wrapper.rs index 77c4a3c..56e9008 100644 --- a/src/view/view_wrapper.rs +++ b/src/view/view_wrapper.rs @@ -1,9 +1,9 @@ use std::any::Any; use vec::Vec2; -use view::{View,SizeRequest,Selector}; +use view::{View, SizeRequest, Selector}; use printer::Printer; -use event::{Event,EventResult}; +use event::{Event, EventResult}; /// Generic wrapper around a view. /// @@ -127,4 +127,3 @@ macro_rules! wrap_impl { } }; } -