This commit is contained in:
Alexandre Bury 2016-07-10 19:11:21 -07:00
parent 6e0819f723
commit c07e8b6aee
10 changed files with 66 additions and 47 deletions

View File

@ -7,7 +7,7 @@ pub struct Align {
} }
impl Align { impl Align {
/// Creates a new Align object from the given horizontal and vertical alignments. /// Creates a new Align object from the given alignments.
pub fn new(h: HAlign, v: VAlign) -> Self { pub fn new(h: HAlign, v: VAlign) -> Self {
Align { h: h, v: v } Align { h: h, v: v }
} }
@ -53,8 +53,11 @@ pub enum VAlign {
} }
impl HAlign { impl HAlign {
/// To draw a view with size `content` in a printer with size `container`, this returns the /// Returns the offset required to position a view.
/// offset to start printing the view at. ///
/// When drawing a view with size `content` when the available size is
/// `container`, printing at the resulting offset will align the view as
/// desired.
pub fn get_offset(&self, content: usize, container: usize) -> usize { pub fn get_offset(&self, content: usize, container: usize) -> usize {
match *self { match *self {
HAlign::Left => 0, HAlign::Left => 0,
@ -65,8 +68,11 @@ impl HAlign {
} }
impl VAlign { impl VAlign {
/// To draw a view with size `content` in a printer with size `container`, this returns the /// Returns the offset required to position a view.
/// offset to start printing the view at. ///
/// When drawing a view with size `content` when the available size is
/// `container`, printing at the resulting offset will align the view as
/// desired.
pub fn get_offset(&self, content: usize, container: usize) -> usize { pub fn get_offset(&self, content: usize, container: usize) -> usize {
match *self { match *self {
VAlign::Top => 0, VAlign::Top => 0,

View File

@ -1,6 +1,6 @@
use backend; use backend;
use event::{Event, Key}; use event::{Event, Key};
use theme; use theme::{Color, ColorStyle, Effect};
use utf8; use utf8;
use ncurses; use ncurses;
@ -18,7 +18,7 @@ impl backend::Backend for NcursesBackend {
ncurses::start_color(); ncurses::start_color();
ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE); ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
ncurses::wbkgd(ncurses::stdscr, ncurses::wbkgd(ncurses::stdscr,
ncurses::COLOR_PAIR(theme::ColorStyle::Background.id())); ncurses::COLOR_PAIR(ColorStyle::Background.id()));
} }
fn screen_size() -> (usize, usize) { fn screen_size() -> (usize, usize) {
@ -37,8 +37,8 @@ impl backend::Backend for NcursesBackend {
} }
fn init_color_style(style: theme::ColorStyle, foreground: &theme::Color, fn init_color_style(style: ColorStyle, foreground: &Color,
background: &theme::Color) { background: &Color) {
// TODO: build the color on the spot // TODO: build the color on the spot
ncurses::init_pair(style.id(), ncurses::init_pair(style.id(),
@ -46,7 +46,7 @@ impl backend::Backend for NcursesBackend {
find_closest(background) as i16); find_closest(background) as i16);
} }
fn with_color<F: FnOnce()>(color: theme::ColorStyle, f: F) { fn with_color<F: FnOnce()>(color: ColorStyle, f: F) {
let mut current_style: ncurses::attr_t = 0; let mut current_style: ncurses::attr_t = 0;
let mut current_color: i16 = 0; let mut current_color: i16 = 0;
ncurses::attr_get(&mut current_style, &mut current_color); ncurses::attr_get(&mut current_style, &mut current_color);
@ -58,10 +58,10 @@ impl backend::Backend for NcursesBackend {
ncurses::attron(current_style); ncurses::attron(current_style);
} }
fn with_effect<F: FnOnce()>(effect: theme::Effect, f: F) { fn with_effect<F: FnOnce()>(effect: Effect, f: F) {
let style = match effect { let style = match effect {
theme::Effect::Reverse => ncurses::A_REVERSE(), Effect::Reverse => ncurses::A_REVERSE(),
theme::Effect::Simple => ncurses::A_NORMAL(), Effect::Simple => ncurses::A_NORMAL(),
}; };
ncurses::attron(style); ncurses::attron(style);
f(); f();
@ -84,9 +84,8 @@ impl backend::Backend for NcursesBackend {
let ch: i32 = ncurses::getch(); let ch: i32 = ncurses::getch();
// Is it a UTF-8 starting point? // Is it a UTF-8 starting point?
if 32 <= ch && ch < 0x100 && ch != 127 { if 32 <= ch && ch <= 255 && ch != 127 {
Event::Char(utf8::read_char(ch as u8, Event::Char(utf8::read_char(ch as u8, || ncurses::getch() as u8)
|| ncurses::getch() as u8)
.unwrap()) .unwrap())
} else { } else {
parse_ncurses_char(ch) parse_ncurses_char(ch)
@ -214,30 +213,29 @@ fn parse_ncurses_char(ch: i32) -> Event {
f @ 289...300 => Event::Ctrl(Key::from_f((f - 288) as u8)), f @ 289...300 => Event::Ctrl(Key::from_f((f - 288) as u8)),
f @ 301...312 => Event::CtrlShift(Key::from_f((f - 300) as u8)), f @ 301...312 => Event::CtrlShift(Key::from_f((f - 300) as u8)),
f @ 313...324 => Event::Alt(Key::from_f((f - 312) as u8)), f @ 313...324 => Event::Alt(Key::from_f((f - 312) as u8)),
// Values 8-10 (H,I,J) are used by other commands, so we won't receive them. // Values 8-10 (H,I,J) are used by other commands,
c @ 1...25 => { // so we probably won't receive them. Meh~
Event::CtrlChar((b'a' + (c - 1) as u8) as char) c @ 1...25 => Event::CtrlChar((b'a' + (c - 1) as u8) as char),
}
_ => Event::Unknown(ch), _ => Event::Unknown(ch),
} }
} }
fn find_closest(color: &theme::Color) -> u8 { fn find_closest(color: &Color) -> u8 {
match *color { match *color {
theme::Color::Black => 0, Color::Black => 0,
theme::Color::Red => 1, Color::Red => 1,
theme::Color::Green => 2, Color::Green => 2,
theme::Color::Yellow => 3, Color::Yellow => 3,
theme::Color::Blue => 4, Color::Blue => 4,
theme::Color::Magenta => 5, Color::Magenta => 5,
theme::Color::Cyan => 6, Color::Cyan => 6,
theme::Color::White => 7, Color::White => 7,
theme::Color::Rgb(r, g, b) => { Color::Rgb(r, g, b) => {
let r = 6 * r as u16 / 256; let r = 6 * r as u16 / 256;
let g = 6 * g as u16 / 256; let g = 6 * g as u16 / 256;
let b = 6 * b as u16 / 256; let b = 6 * b as u16 / 256;
(16 + 36 * r + 6 * g + b) as u8 (16 + 36 * r + 6 * g + b) as u8
} }
theme::Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as u8, Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as u8,
} }
} }

View File

@ -141,7 +141,6 @@ pub enum Event {
/// A non-character key was pressed with the Ctrl and Alt keys pressed /// A non-character key was pressed with the Ctrl and Alt keys pressed
CtrlAlt(Key), CtrlAlt(Key),
/// An unknown event was received. /// An unknown event was received.
Unknown(i32), Unknown(i32),
} }

View File

@ -20,7 +20,7 @@
//! siv.run(); //! siv.run();
//! } //! }
//! ``` //! ```
// #![deny(missing_docs)] //! #![deny(missing_docs)]
extern crate ncurses; extern crate ncurses;
extern crate toml; extern crate toml;

View File

@ -11,8 +11,10 @@ pub enum Orientation {
} }
impl Orientation { impl Orientation {
/// Returns the component of the given vector corresponding to this orientation. /// Returns the component of `v` corresponding to this orientation.
/// (Horizontal will return the x value, and Vertical will return the y value.) ///
/// (`Horizontal` will return the x value,
/// and `Vertical` will return the y value.)
pub fn get(&self, v: &Vec2) -> usize { pub fn get(&self, v: &Vec2) -> usize {
match *self { match *self {
Orientation::Horizontal => v.x, Orientation::Horizontal => v.x,

View File

@ -314,9 +314,11 @@ impl Color {
} }
/// Loads a theme file, and returns its representation if everything worked well. /// Loads a theme file, and returns its representation.
/// ///
/// The file should be a toml file. All fields are optional. Here is are the possible entries: /// The file should be a toml file. All fields are optional.
///
/// Here are the possible entries:
/// ///
/// ```text /// ```text
/// # Every field in a theme file is optional. /// # Every field in a theme file is optional.

View File

@ -1,6 +1,9 @@
use std::char::from_u32; use std::char::from_u32;
/// Reads a char from a first byte, and a function to fetch next bytes as required. /// Reads a potentially multi-bytes utf8 codepoint.
///
/// Reads the given first byte, and uses the given
/// function to get more if needed.
/// ///
/// Returns an error if the stream is invalid utf-8. /// Returns an error if the stream is invalid utf-8.
pub fn read_char<F>(first: u8, next: F) -> Result<char, String> pub fn read_char<F>(first: u8, next: F) -> Result<char, String>

View File

@ -117,7 +117,9 @@ impl View for LinearLayout {
// Use pre-computed sizes // Use pre-computed sizes
let mut offset = Vec2::zero(); 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)); let printer =
&printer.sub_printer(offset, child.size, i == self.focus);
child.view.draw(printer);
// On the axis given by the orientation, // On the axis given by the orientation,
// add the child size to the offset. // add the child size to the offset.
@ -151,7 +153,8 @@ impl View for LinearLayout {
let min_size = self.orientation.stack(min_sizes.iter()); let min_size = self.orientation.stack(min_sizes.iter());
// Emulate 'non-strict inequality' on integers // Emulate 'non-strict inequality' on integers
// (default comparison on Vec2 is strict, and (0,1).cmp((1,1)) is undefined) // (default comparison on Vec2 is strict,
// and (0,1).cmp((1,1)) is undefined)
if !(min_size < size + (1, 1)) { if !(min_size < size + (1, 1)) {
// Error! Not enough space! Emergency procedures! // Error! Not enough space! Emergency procedures!
return; return;
@ -208,7 +211,7 @@ impl View for LinearLayout {
EventResult::Consumed(None) EventResult::Consumed(None)
} }
Event::Shift(Key::Tab) if self.focus + 1 < Event::Shift(Key::Tab) if self.focus + 1 <
self.children.len() => { self.children.len() => {
self.focus += 1; self.focus += 1;
EventResult::Consumed(None) EventResult::Consumed(None)
} }

View File

@ -75,13 +75,17 @@ impl ScrollBase {
self.start_line = self.content_height - self.view_height; self.start_line = self.content_height - self.view_height;
} }
/// Scroll down by the given number of line, never going further than the bottom of the view. /// Scroll down by the given number of line.
///
/// Never further than the bottom of the view.
pub fn scroll_down(&mut self, n: usize) { pub fn scroll_down(&mut self, n: usize) {
self.start_line = min(self.start_line + n, self.start_line = min(self.start_line + n,
self.content_height - self.view_height); self.content_height - self.view_height);
} }
/// Scroll up by the given number of lines, never going above the top of the view. /// Scroll up by the given number of lines.
///
/// Never above the top of the view.
pub fn scroll_up(&mut self, n: usize) { pub fn scroll_up(&mut self, n: usize) {
self.start_line -= min(self.start_line, n); self.start_line -= min(self.start_line, n);
} }
@ -130,7 +134,8 @@ impl ScrollBase {
// And draw the scrollbar if needed // And draw the scrollbar if needed
if self.view_height < self.content_height { if self.view_height < self.content_height {
// We directly compute the size of the scrollbar (this allow use to avoid using floats). // We directly compute the size of the scrollbar
// (that way we avoid using floats).
// (ratio) * max_height // (ratio) * max_height
// Where ratio is ({start or end} / content.height) // Where ratio is ({start or end} / content.height)
let height = max(1, let height = max(1,

View File

@ -10,9 +10,10 @@ use event::{Event, EventResult};
/// Default implementation forwards all calls to the child view. /// Default implementation forwards all calls to the child view.
/// Overrides some methods as desired. /// Overrides some methods as desired.
pub trait ViewWrapper { pub trait ViewWrapper {
/// Get an immutable reference to the wrapped view, so that we can forward some calls to it. /// Get an immutable reference to the wrapped view.
fn get_view(&self) -> &View; fn get_view(&self) -> &View;
/// Get a mutable reference to the wrapped view, for the mutable methods.
/// Get a mutable reference to the wrapped view.
fn get_view_mut(&mut self) -> &mut View; fn get_view_mut(&mut self) -> &mut View;
/// Wraps the draw method. /// Wraps the draw method.
@ -79,7 +80,7 @@ impl<T: ViewWrapper> View for T {
} }
} }
/// Convenient macro to implement to two methods required for the ViewWrapper trait. /// Convenient macro to implement the ViewWrapper trait.
/// ///
/// # Examples /// # Examples
/// ///