Apply rustfmt

This commit is contained in:
Alexandre Bury 2016-07-09 19:05:51 -07:00
parent 08ab18608b
commit 4b095a0652
20 changed files with 283 additions and 221 deletions

View File

@ -37,8 +37,7 @@ impl backend::Backend for NcursesBackend {
}
fn init_color_style(style: theme::ColorStyle,
foreground: &theme::Color,
fn init_color_style(style: theme::ColorStyle, foreground: &theme::Color,
background: &theme::Color) {
// TODO: build the color on the spot
@ -86,7 +85,9 @@ impl backend::Backend for NcursesBackend {
// Is it a UTF-8 starting point?
if 32 <= ch && ch < 0x100 && ch != 127 {
event::Event::Char(utf8::read_char(ch as u8, || ncurses::getch() as u8).unwrap())
event::Event::Char(utf8::read_char(ch as u8,
|| ncurses::getch() as u8)
.unwrap())
} else {
event::Event::Key(parse_ncurses_char(ch))
}
@ -110,12 +111,14 @@ fn parse_ncurses_char(ch: i32) -> event::Key {
// Tab is '\t'
9 => event::Key::Tab,
// Treat '\n' and the numpad Enter the same
10 | ncurses::KEY_ENTER => event::Key::Enter,
10 |
ncurses::KEY_ENTER => event::Key::Enter,
// This is the escape key when pressed by itself.
// When used for control sequences, it should have been caught earlier.
27 => event::Key::Esc,
// `Backspace` sends 127, but Ctrl-H sends `Backspace`
127 | ncurses::KEY_BACKSPACE => event::Key::Backspace,
127 |
ncurses::KEY_BACKSPACE => event::Key::Backspace,
410 => event::Key::Resize,
@ -204,7 +207,9 @@ fn parse_ncurses_char(ch: i32) -> event::Key {
ncurses::KEY_SNEXT => event::Key::ShiftPageDown,
ncurses::KEY_SPREVIOUS => event::Key::ShiftPageUp,
// All Fn keys use the same enum with associated number
f @ ncurses::KEY_F1...ncurses::KEY_F12 => event::Key::F((f - ncurses::KEY_F0) as u8),
f @ ncurses::KEY_F1...ncurses::KEY_F12 => {
event::Key::F((f - ncurses::KEY_F0) as u8)
}
f @ 277...288 => event::Key::ShiftF((f - 277) as u8),
f @ 289...300 => event::Key::CtrlF((f - 289) as u8),
f @ 301...312 => event::Key::CtrlShiftF((f - 300) as u8),
@ -213,7 +218,9 @@ fn parse_ncurses_char(ch: i32) -> event::Key {
//
// TODO: shift and ctrl Fn keys
// Avoids 8-10 (H,I,J), they are used by other commands.
c @ 1...7 | c @ 11...25 => event::Key::CtrlChar((b'a' + (c - 1) as u8) as char),
c @ 1...7 | c @ 11...25 => {
event::Key::CtrlChar((b'a' + (c - 1) as u8) as char)
}
_ => event::Key::Unknown(ch),
}
}
@ -234,8 +241,6 @@ fn find_closest(color: &theme::Color) -> u8 {
let b = 6 * b as u16 / 256;
(16 + 36 * r + 6 * g + b) as u8
}
theme::Color::RgbLowRes(r, g, b) => {
(16 + 36 * r + 6 * g + b) as u8
}
theme::Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as u8,
}
}

View File

@ -7,7 +7,6 @@ mod curses;
pub use self::curses::NcursesBackend;
pub trait Backend {
fn init();
fn finish();
@ -16,8 +15,7 @@ pub trait Backend {
fn has_colors() -> bool;
fn init_color_style(style: theme::ColorStyle,
foreground: &theme::Color,
fn init_color_style(style: theme::ColorStyle, foreground: &theme::Color,
background: &theme::Color);
fn print_at((usize, usize), &str);

View File

@ -1,16 +1,15 @@
/*
/// Integer division that rounds up.
pub fn div_up_usize(p: usize, q: usize) -> usize {
div_up(p as u32, q as u32) as 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
}
}
*/
// Integer division that rounds up.
// pub fn div_up_usize(p: usize, q: usize) -> usize {
// div_up(p as u32, q as u32) as 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
// }
// }
//

View File

@ -153,8 +153,10 @@ impl Cursive {
true
}
/// Regularly redraws everything, even when no input is given. Between 0 and 1000.
/// Sets the refresh rate, in frames per second.
///
/// Regularly redraws everything, even when no input is given.
/// Between 0 and 1000.
/// Call with fps=0 to disable (default value).
pub fn set_fps(&self, fps: u32) {
B::set_refresh_rate(fps)
@ -199,8 +201,8 @@ impl Cursive {
/// Tries to find the view pointed to by the given path.
/// If the view is not found, or if it is not of the asked type,
/// it returns None.
pub fn find<V: View + Any>(&mut self, selector: &Selector) -> Option<&mut V> {
match self.find_any(selector) {
pub fn find<V: View + Any>(&mut self, sel: &Selector) -> Option<&mut V> {
match self.find_any(sel) {
None => None,
Some(b) => b.downcast_mut::<V>(),
}
@ -211,7 +213,9 @@ impl Cursive {
self.find(&Selector::Id(id))
}
/// Adds a global callback, triggered on the given key press when no view catches it.
/// Adds a global callback.
///
/// Will be triggered on the given key press when no view catches it.
pub fn add_global_callback<F, E: ToEvent>(&mut self, event: E, cb: F)
where F: Fn(&mut Cursive) + 'static
{
@ -267,21 +271,26 @@ impl Cursive {
};
// Draw the menubar?
if self.menubar.visible() {
let printer = printer.sub_printer(Vec2::zero(), printer.size, self.menubar.receive_events());
let printer = printer.sub_printer(Vec2::zero(),
printer.size,
self.menubar.receive_events());
self.menubar.draw(&printer);
}
let selected = self.menubar.receive_events();
self.screen_mut()
.draw(&printer.sub_printer(Vec2::new(0, offset), printer.size, !selected));
let printer =
printer.sub_printer(Vec2::new(0, offset), printer.size, !selected);
self.screen_mut().draw(&printer);
B::refresh();
}
/// Runs the event loop.
///
/// It will wait for user input (key presses) and trigger callbacks accordingly.
/// It will wait for user input (key presses)
/// and trigger callbacks accordingly.
///
/// Blocks until quit() is called.
pub fn run(&mut self) {
@ -315,7 +324,8 @@ impl Cursive {
}
} else {
match self.screen_mut().on_event(event) {
// If the event was ignored, it is our turn to play with it.
// If the event was ignored,
// it is our turn to play with it.
EventResult::Ignored => self.on_event(event),
EventResult::Consumed(None) => (),
EventResult::Consumed(Some(cb)) => cb(self),

View File

@ -31,7 +31,7 @@ impl MenuItem {
pub fn is_subtree(&self) -> bool {
match *self {
MenuItem::Subtree(_,_) => true,
MenuItem::Subtree(_, _) => true,
_ => false,
}
}
@ -62,7 +62,8 @@ impl MenuTree {
self.with(|menu| menu.add_delimiter())
}
pub fn add_leaf<F: 'static + Fn(&mut Cursive)>(&mut self, title: &str, cb: F) {
pub fn add_leaf<F: 'static + Fn(&mut Cursive)>(&mut self, title: &str,
cb: F) {
self.children
.push(MenuItem::Leaf(title.to_string(), Rc::new(cb)));
}

View File

@ -1,3 +1,4 @@
use Cursive;
use menu::MenuTree;
use view::MenuPopup;
use view::KeyEventView;
@ -109,42 +110,18 @@ impl Menubar {
let menu = self.menus[self.focus].1.clone();
self.state = State::Submenu;
let offset = (self.menus[..self.focus]
.iter()
.map(|&(ref title, _)| title.width() + 2)
.fold(0, |a, b| a + b),
.iter()
.map(|&(ref title, _)| title.width() + 2)
.fold(0, |a, b| a + b),
if self.autohide {
1
} else {
0
});
// Since the closure will be called multiple times,
// we also need a new Rc on every call.
return Some(Rc::new(move |s| {
// Since the closure will be called multiple times,
// we also need a new Rc on every call.
s.screen_mut()
.add_layer_at(Position::absolute(offset),
KeyEventView::new(MenuPopup::new(menu.clone())
.on_dismiss(|s| s.select_menubar())
.on_action(|s| {
s.menubar().state = State::Inactive
}))
.register(Key::Right, |s| {
s.pop_layer();
// Act as if we sent "Left" then "Enter"
s.select_menubar();
s.menubar().on_event(Event::Key(Key::Right));
if let Some(cb) = s.menubar().on_event(Event::Key(Key::Down)) {
cb(s);
}
})
.register(Key::Left, |s| {
s.pop_layer();
// Act as if we sent "Left" then "Enter"
s.select_menubar();
s.menubar().on_event(Event::Key(Key::Left));
if let Some(cb) = s.menubar().on_event(Event::Key(Key::Down)) {
cb(s);
}
}));
show_child(s, offset, menu.clone())
}));
}
_ => (),
@ -152,3 +129,34 @@ impl Menubar {
None
}
}
fn show_child(s: &mut Cursive, offset: (usize, usize), menu: Rc<MenuTree>) {
s.screen_mut()
.add_layer_at(Position::absolute(offset),
KeyEventView::new(MenuPopup::new(menu)
.on_dismiss(|s| s.select_menubar())
.on_action(|s| {
s.menubar().state = State::Inactive
}))
.register(Key::Right, |s| {
s.pop_layer();
// Act as if we sent "Left" then "Enter"
s.select_menubar();
s.menubar().on_event(Event::Key(Key::Right));
if let Some(cb) = s.menubar()
.on_event(Event::Key(Key::Down)) {
cb(s);
}
})
.register(Key::Left, |s| {
s.pop_layer();
// Act as if we sent "Left" then "Enter"
s.select_menubar();
s.menubar().on_event(Event::Key(Key::Left));
if let Some(cb) = s.menubar()
.on_event(Event::Key(Key::Down)) {
cb(s);
}
}));
}

View File

@ -44,8 +44,12 @@ impl Orientation {
/// For a vertical view, returns (Max(x),Sum(y)).
pub fn stack<'a, T: Iterator<Item = &'a Vec2>>(&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))
}
}
}
}

View File

@ -6,7 +6,7 @@ use backend::Backend;
use B;
use theme::{ColorStyle, Theme, Effect};
use theme::{ColorStyle, Effect, Theme};
use vec::{ToVec2, Vec2};
/// Convenient interface to draw on a subset of the screen.
@ -136,20 +136,25 @@ impl Printer {
self.print_hline(start_v + (1, 0), size_v.x - 1, "");
self.print_vline(start_v + (0, 1), size_v.y - 1, "");
self.print_hline(start_v + (1, 0) + size_v.keep_y(), size_v.x - 1, "");
self.print_vline(start_v + (0, 1) + size_v.keep_x(), size_v.y - 1, "");
self.print_hline(start_v + (1, 0) + size_v.keep_y(),
size_v.x - 1,
"");
self.print_vline(start_v + (0, 1) + size_v.keep_x(),
size_v.y - 1,
"");
}
pub fn with_selection<F: FnOnce(&Printer)>(&self, selection: bool, f: F) {
self.with_color(if selection {
if self.focused {
ColorStyle::Highlight
} else {
ColorStyle::HighlightInactive
}
} else {
ColorStyle::Primary
}, f);
if self.focused {
ColorStyle::Highlight
} else {
ColorStyle::HighlightInactive
}
} else {
ColorStyle::Primary
},
f);
}
pub fn print_hdelim<T: ToVec2>(&self, start: T, len: usize) {
@ -160,7 +165,8 @@ impl Printer {
}
/// Returns a printer on a subset of this one's area.
pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool) -> Printer {
pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool)
-> Printer {
let offset_v = offset.to_vec2();
Printer {
offset: self.offset + offset_v,

View File

@ -112,32 +112,32 @@ impl Theme {
fn activate(&self) {
// Initialize each color with the backend
B::init_color_style(ColorStyle::Background,
&self.colors.view,
&self.colors.background);
&self.colors.view,
&self.colors.background);
B::init_color_style(ColorStyle::Shadow,
&self.colors.shadow,
&self.colors.shadow);
&self.colors.shadow,
&self.colors.shadow);
B::init_color_style(ColorStyle::Primary,
&self.colors.primary,
&self.colors.view);
&self.colors.primary,
&self.colors.view);
B::init_color_style(ColorStyle::Secondary,
&self.colors.secondary,
&self.colors.view);
&self.colors.secondary,
&self.colors.view);
B::init_color_style(ColorStyle::Tertiary,
&self.colors.tertiary,
&self.colors.view);
&self.colors.tertiary,
&self.colors.view);
B::init_color_style(ColorStyle::TitlePrimary,
&self.colors.title_primary,
&self.colors.view);
&self.colors.title_primary,
&self.colors.view);
B::init_color_style(ColorStyle::TitleSecondary,
&self.colors.title_secondary,
&self.colors.view);
&self.colors.title_secondary,
&self.colors.view);
B::init_color_style(ColorStyle::Highlight,
&self.colors.view,
&self.colors.highlight);
&self.colors.view,
&self.colors.highlight);
B::init_color_style(ColorStyle::HighlightInactive,
&self.colors.view,
&self.colors.highlight_inactive);
&self.colors.view,
&self.colors.highlight_inactive);
}
}
@ -207,20 +207,25 @@ impl Palette {
load_color(&mut self.title_primary, table.get("title_primary"));
load_color(&mut self.title_secondary, table.get("title_secondary"));
load_color(&mut self.highlight, table.get("highlight"));
load_color(&mut self.highlight_inactive, table.get("highlight_inactive"));
load_color(&mut self.highlight_inactive,
table.get("highlight_inactive"));
}
}
fn load_color(target: &mut Color, value: Option<&toml::Value>) -> bool {
if let Some(value) = value {
match *value {
toml::Value::String(ref value) => if let Some(color) = Color::parse(value) {
*target = color;
true
} else {
false
},
toml::Value::Array(ref array) => array.iter().any(|item| load_color(target, Some(item))),
toml::Value::String(ref value) => {
if let Some(color) = Color::parse(value) {
*target = color;
true
} else {
false
}
}
toml::Value::Array(ref array) => {
array.iter().any(|item| load_color(target, Some(item)))
}
_ => false,
}
} else {
@ -245,8 +250,7 @@ pub enum Color {
RgbLowRes(u8, u8, u8),
}
impl Color {
}
impl Color {}
/// Possible error returned when loading a theme.
#[derive(Debug)]
@ -294,9 +298,12 @@ impl Color {
Some(Color::Rgb(r as u8, g as u8, b as u8))
} else if value.len() == 3 {
// RGB values between 0 and 5 maybe?
let rgb: Vec<_> = value.chars().map(|c| c as i16 - '0' as i16).collect();
let rgb: Vec<_> =
value.chars().map(|c| c as i16 - '0' as i16).collect();
if rgb.iter().all(|&i| i >= 0 && i < 6) {
Some(Color::RgbLowRes(rgb[0] as u8, rgb[1] as u8, rgb[2] as u8))
Some(Color::RgbLowRes(rgb[0] as u8,
rgb[1] as u8,
rgb[2] as u8))
} else {
None
}

View File

@ -3,7 +3,7 @@ use std::rc::Rc;
use theme::ColorStyle;
use Cursive;
use vec::Vec2;
use view::{View};
use view::View;
use event::*;
use printer::Printer;
use unicode_width::UnicodeWidthStr;
@ -51,7 +51,9 @@ impl View for Button {
fn on_event(&mut self, event: Event) -> EventResult {
match event {
// 10 is the ascii code for '\n', that is the return key
Event::Key(Key::Enter) => EventResult::Consumed(Some(self.callback.clone())),
Event::Key(Key::Enter) => {
EventResult::Consumed(Some(self.callback.clone()))
}
_ => EventResult::Ignored,
}
}

View File

@ -55,7 +55,9 @@ impl EditView {
&self.content
}
/// Sets the current content to the given value. Convenient chainable method.
/// Sets the current content to the given value.
///
/// Convenient chainable method.
pub fn content(mut self, content: &str) -> Self {
self.set_content(content);
self
@ -77,7 +79,6 @@ impl EditView {
impl View for EditView {
fn draw(&mut self, printer: &Printer) {
// let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE };
assert!(printer.size.x == self.last_length);
let width = self.content.width();
@ -92,16 +93,16 @@ impl View for EditView {
} else {
let content = &self.content[self.offset..];
let display_bytes = content.graphemes(true)
.scan(0, |w, g| {
*w += g.width();
if *w > self.last_length {
None
} else {
Some(g)
}
})
.map(|g| g.len())
.fold(0, |a, b| a + b);
.scan(0, |w, g| {
*w += g.width();
if *w > self.last_length {
None
} else {
Some(g)
}
})
.map(|g| g.len())
.fold(0, |a, b| a + b);
let content = &content[..display_bytes];
@ -163,26 +164,26 @@ impl View for EditView {
Key::End => self.cursor = self.content.len(),
Key::Left if self.cursor > 0 => {
let len = self.content[..self.cursor]
.graphemes(true)
.last()
.unwrap()
.len();
.graphemes(true)
.last()
.unwrap()
.len();
self.cursor -= len;
}
Key::Right if self.cursor < self.content.len() => {
let len = self.content[self.cursor..]
.graphemes(true)
.next()
.unwrap()
.len();
.graphemes(true)
.next()
.unwrap()
.len();
self.cursor += len;
}
Key::Backspace if self.cursor > 0 => {
let len = self.content[..self.cursor]
.graphemes(true)
.last()
.unwrap()
.len();
.graphemes(true)
.last()
.unwrap()
.len();
self.cursor -= len;
self.content.remove(self.cursor);
}
@ -196,18 +197,21 @@ impl View for EditView {
// Keep cursor in [offset, offset+last_length] by changing offset
// So keep offset in [last_length-cursor,cursor]
// Also call this on resize, but right now it is an event like any other
// Also call this on resize,
// but right now it is an event like any other
if self.cursor < self.offset {
self.offset = self.cursor;
} else {
// So we're against the right wall.
// Let's find how much space will be taken by the selection (either a char, or _)
// Let's find how much space will be taken by the selection
// (either a char, or _)
let c_len = self.content[self.cursor..]
.graphemes(true)
.map(|g| g.width())
.next()
.unwrap_or(1);
// Now, we have to fit self.content[..self.cursor] into self.last_length - c_len.
.graphemes(true)
.map(|g| g.width())
.next()
.unwrap_or(1);
// Now, we have to fit self.content[..self.cursor]
// into self.last_length - c_len.
let available = self.last_length - c_len;
// Look at the content before the cursor (we will print its tail).
// From the end, count the length until we reach `available`.

View File

@ -118,7 +118,7 @@ impl View for LinearLayout {
// On the axis given by the orientation,
// add the child size to the offset.
*self.orientation.get_ref(&mut offset) += self.orientation
.get(&child.size);
.get(&child.size);
}
}
@ -127,9 +127,9 @@ impl View for LinearLayout {
// Look how mean we are: we offer the whole size to every child.
// As if they could get it all.
let min_sizes: Vec<Vec2> = self.children
.iter_mut()
.map(|child| Vec2::min(size, child.view.get_min_size(size)))
.collect();
.iter_mut()
.map(|child| Vec2::min(size, child.view.get_min_size(size)))
.collect();
let min_size = self.orientation.stack(min_sizes.iter());
// Emulate 'non-strict inequality' on integers
@ -150,11 +150,12 @@ impl View for LinearLayout {
for (child, (child_size, extra)) in self.children
.iter_mut()
.zip(min_sizes.iter().zip(extras.iter())) {
.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);
*self.orientation.swap().get_ref(&mut child_size) =
self.orientation.swap().get(&size);
child.size = child_size;
child.view.layout(child_size);
}
@ -163,9 +164,9 @@ impl View for LinearLayout {
fn get_min_size(&mut self, req: Vec2) -> Vec2 {
// First, make a naive scenario: everything will work fine.
let sizes: Vec<Vec2> = self.children
.iter_mut()
.map(|view| view.view.get_min_size(req))
.collect();
.iter_mut()
.map(|view| view.view.get_min_size(req))
.collect();
self.orientation.stack(sizes.iter())
@ -188,27 +189,34 @@ impl View for LinearLayout {
self.focus -= 1;
EventResult::Consumed(None)
}
Event::Key(Key::ShiftTab) if self.focus + 1 < self.children.len() => {
Event::Key(Key::ShiftTab) if self.focus + 1 <
self.children.len() => {
self.focus += 1;
EventResult::Consumed(None)
}
Event::Key(Key::Left) if self.orientation == Orientation::Horizontal &&
Event::Key(Key::Left) if self.orientation ==
Orientation::Horizontal &&
self.focus > 0 => {
self.focus -= 1;
EventResult::Consumed(None)
}
Event::Key(Key::Up) if self.orientation == Orientation::Vertical &&
Event::Key(Key::Up) if self.orientation ==
Orientation::Vertical &&
self.focus > 0 => {
self.focus -= 1;
EventResult::Consumed(None)
}
Event::Key(Key::Right) if self.orientation == Orientation::Horizontal &&
self.focus + 1 < self.children.len() => {
Event::Key(Key::Right) if self.orientation ==
Orientation::Horizontal &&
self.focus + 1 <
self.children.len() => {
self.focus += 1;
EventResult::Consumed(None)
}
Event::Key(Key::Down) if self.orientation == Orientation::Vertical &&
self.focus + 1 < self.children.len() => {
Event::Key(Key::Down) if self.orientation ==
Orientation::Vertical &&
self.focus + 1 <
self.children.len() => {
self.focus += 1;
EventResult::Consumed(None)
}

View File

@ -96,28 +96,28 @@ impl MenuPopup {
let tree = tree.clone();
let max_width = 4 +
self.menu
.children
.iter()
.map(Self::item_width)
.max()
.unwrap_or(1);
.children
.iter()
.map(Self::item_width)
.max()
.unwrap_or(1);
let offset = Vec2::new(max_width, self.focus);
let action_cb = self.on_action.clone();
EventResult::with_cb(move |s| {
let action_cb = action_cb.clone();
s.screen_mut()
.add_layer_at(Position::parent(offset),
KeyEventView::new(MenuPopup::new(tree.clone())
.on_action(move |s| {
// This will happen when the subtree popup
// activates something;
// First, remove ourselve.
s.pop_layer();
.add_layer_at(Position::parent(offset),
KeyEventView::new(MenuPopup::new(tree.clone())
.on_action(move |s| {
// This will happen when the subtree popup
// activates something;
// First, remove ourselve.
s.pop_layer();
if let Some(ref action_cb) = action_cb {
action_cb.clone()(s);
}
}))
.register(Key::Left, |s| s.pop_layer()));
}))
.register(Key::Left, |s| s.pop_layer()));
})
}
}
@ -126,9 +126,8 @@ impl View for MenuPopup {
fn draw(&mut self, printer: &Printer) {
let h = self.menu.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);
// Start with a box
printer.print_box(Vec2::new(0, 0), printer.size);
@ -164,11 +163,11 @@ impl View for MenuPopup {
// We can't really shrink our items here, so it's not flexible.
let w = 4 +
self.menu
.children
.iter()
.map(Self::item_width)
.max()
.unwrap_or(1);
.children
.iter()
.map(Self::item_width)
.max()
.unwrap_or(1);
let h = 2 + self.menu.children.len();
@ -203,7 +202,7 @@ impl View for MenuPopup {
Event::Key(Key::End) => self.focus = self.menu.children.len() - 1,
Event::Key(Key::Right) if self.menu.children[self.focus]
.is_subtree() => {
.is_subtree() => {
return match self.menu.children[self.focus] {
MenuItem::Subtree(_, ref tree) => {
self.make_subtree_cb(tree)
@ -213,7 +212,7 @@ impl View for MenuPopup {
};
}
Event::Key(Key::Enter) if !self.menu.children[self.focus]
.is_delimiter() => {
.is_delimiter() => {
return match self.menu.children[self.focus] {
MenuItem::Leaf(_, ref cb) => {

View File

@ -34,7 +34,7 @@ use event::{Event, EventResult};
use vec::Vec2;
use printer::Printer;
pub use self::position::{Position, Offset};
pub use self::position::{Offset, Position};
pub use self::scroll::ScrollBase;
@ -64,7 +64,7 @@ pub trait View {
EventResult::Ignored
}
/// Returns the minimum size the view requires under the given restrictions.
/// Returns the minimum size the view requires with the given restrictions.
fn get_min_size(&mut self, Vec2) -> Vec2 {
Vec2::new(1, 1)
}

View File

@ -27,7 +27,8 @@ impl Position {
Position::new(Offset::Parent(offset.x), Offset::Parent(offset.y))
}
pub fn compute_offset(&self, size: Vec2, available: Vec2, parent: Vec2) -> Vec2 {
pub fn compute_offset(&self, size: Vec2, available: Vec2, parent: Vec2)
-> Vec2 {
Vec2::new(self.x.compute_offset(size.x, available.x, parent.x),
self.y.compute_offset(size.y, available.y, parent.y))
}
@ -40,14 +41,15 @@ pub enum Offset {
/// Place top-left corner at the given absolute coordinates
Absolute(usize),
/// Place top-left corner at the given offset from the previous layer's top-left corner.
/// Offset from the previous layer's top-left corner.
///
/// If this is the first layer, behaves like `Absolute`.
Parent(usize), // TODO: use a signed vec for negative offset?
}
impl Offset {
pub fn compute_offset(&self, size: usize, available: usize, parent: usize) -> usize {
pub fn compute_offset(&self, size: usize, available: usize, parent: usize)
-> usize {
match *self {
Offset::Center => (available - size) / 2,
Offset::Absolute(offset) => min(offset, available - size),

View File

@ -34,7 +34,8 @@ impl ScrollBase {
self.content_height = content_height;
if self.scrollable() {
self.start_line = min(self.start_line, self.content_height - self.view_height);
self.start_line = min(self.start_line,
self.content_height - self.view_height);
} else {
self.start_line = 0;
}
@ -76,7 +77,8 @@ 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.
@ -109,7 +111,8 @@ impl ScrollBase {
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 max_y = min(self.view_height,
self.content_height - self.start_line);
let w = if self.scrollable() {
printer.size.x - 1 // TODO: 2
} else {
@ -118,7 +121,9 @@ impl ScrollBase {
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),
line_drawer(&printer.sub_printer(Vec2::new(0, y),
Vec2::new(w, 1),
true),
y + self.start_line);
}
@ -128,12 +133,15 @@ 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 start = steps * self.start_line /
(1 + self.content_height - self.view_height);
let color = if printer.focused {
ColorStyle::Highlight

View File

@ -130,9 +130,8 @@ impl<T: 'static> View for SelectView<T> {
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| {
printer.with_selection(i == self.focus, |printer| {
@ -150,10 +149,10 @@ impl<T: 'static> View for SelectView<T> {
// So no matter what the horizontal requirements are,
// we'll still return our longest item.
let w = self.items
.iter()
.map(|item| item.label.width())
.max()
.unwrap_or(1);
.iter()
.map(|item| item.label.width())
.max()
.unwrap_or(1);
let h = self.items.len();
let scrolling = req.y < h;
@ -184,7 +183,9 @@ impl<T: 'static> View for SelectView<T> {
let cb = self.select_cb.as_ref().unwrap().clone();
let v = self.selection();
// We return a Callback Rc<|s| cb(s, &*v)>
return EventResult::Consumed(Some(Rc::new(move |s| cb(s, &*v))));
return EventResult::Consumed(Some(Rc::new(move |s| {
cb(s, &*v)
})));
}
Event::Char(c) => {
// Starting from the current focus,
@ -194,10 +195,8 @@ impl<T: 'static> View for SelectView<T> {
// 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)
}) {
.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();

View File

@ -23,8 +23,7 @@ impl<T: View> ShadowView<T> {
}
fn padding(&self) -> (usize, usize) {
(1 + self.left_padding as usize,
1 + self.top_padding as usize)
(1 + self.left_padding as usize, 1 + self.top_padding as usize)
}
pub fn left_padding(mut self, value: bool) -> Self {
@ -35,7 +34,6 @@ impl<T: View> ShadowView<T> {
self.top_padding = value;
self
}
}
impl<T: View> ViewWrapper for ShadowView<T> {
@ -54,7 +52,11 @@ impl<T: View> ViewWrapper for ShadowView<T> {
fn wrap_draw(&mut self, printer: &Printer) {
// Skip the first row/column
let printer = &printer.sub_printer(Vec2::new(self.left_padding as usize, self.top_padding as usize), printer.size, true);
let printer =
&printer.sub_printer(Vec2::new(self.left_padding as usize,
self.top_padding as usize),
printer.size,
true);
// Draw the view background
for y in 0..printer.size.y - 1 {
@ -69,8 +71,8 @@ impl<T: View> ViewWrapper for ShadowView<T> {
let w = printer.size.x;
printer.with_color(ColorStyle::Shadow, |printer| {
printer.print_hline((1, h-1), w - 1, " ");
printer.print_vline((w-1, 1), h - 1, " ");
printer.print_hline((1, h - 1), w - 1, " ");
printer.print_vline((w - 1, 1), h - 1, " ");
});
}
}

View File

@ -44,8 +44,8 @@ impl StackView {
self.layers.push(Layer {
// Skip padding for absolute/parent-placed views
view: Box::new(ShadowView::new(view)
.top_padding(position.y == Offset::Center)
.left_padding(position.x == Offset::Center)),
.top_padding(position.y == Offset::Center)
.left_padding(position.x == Offset::Center)),
size: Vec2::new(0, 0),
position: position,
virgin: true,
@ -68,11 +68,11 @@ impl View for StackView {
// Place the view
// Center the view
let offset = v.position
.compute_offset(v.size, printer.size, previous);
.compute_offset(v.size, printer.size, previous);
previous = offset;
v.view
.draw(&printer.sub_printer(offset, v.size, i + 1 == last));
.draw(&printer.sub_printer(offset, v.size, i + 1 == last));
}
});
}

View File

@ -7,7 +7,7 @@ pub struct TrackedView<T: View> {
pub offset: Vec2,
}
impl <T: View> TrackedView<T> {
impl<T: View> TrackedView<T> {
pub fn new(view: T) -> Self {
TrackedView {
view: view,