Add printer abstraction on ncurses::WINDOW

Also rename Size -> Vec2
This commit is contained in:
Alexandre Bury 2015-05-15 11:58:47 -07:00
parent 4ebb422611
commit e5c623bb07
7 changed files with 136 additions and 66 deletions

View File

@ -1,11 +1,11 @@
use ncurses;
use event::EventResult;
use super::{Size,ToSize};
use vec2::{Vec2,ToVec2};
use view::{View,SizeRequest};
use printer::Printer;
/// BoxView is a wrapper around an other view, with a given minimum size.
pub struct BoxView {
size: Size,
size: Vec2,
content: Box<View>,
}
@ -19,9 +19,9 @@ impl BoxView {
/// // Creates a 20x4 BoxView with a TextView content.
/// let box = BoxView::new((20,4), TextView::new("Hello!"))
/// ```
pub fn new<S: ToSize, V: View + 'static>(size: S, view: V) -> Self {
pub fn new<S: ToVec2, V: View + 'static>(size: S, view: V) -> Self {
BoxView {
size: size.to_size(),
size: size.to_vec2(),
content: Box::new(view),
}
}
@ -32,15 +32,15 @@ impl View for BoxView {
self.content.on_key_event(ch)
}
fn draw(&self, win: ncurses::WINDOW, size: Size) {
self.content.draw(win, size)
fn draw(&self, printer: &Printer) {
self.content.draw(printer)
}
fn get_min_size(&self, _: SizeRequest) -> Size {
fn get_min_size(&self, _: SizeRequest) -> Vec2 {
self.size
}
fn layout(&mut self, size: Size) {
fn layout(&mut self, size: Vec2) {
self.content.layout(size);
}
}

View File

@ -1,9 +1,13 @@
extern crate ncurses;
/// Module for user-input events and their effects.
/// User-input events and their effects.
pub mod event;
/// Define various views to use when creating the layout.
/// Defines various views to use when creating the layout.
pub mod view;
/// Makes drawing on ncurses windows easier.
pub mod printer;
/// 2D points.
pub mod vec2;
mod box_view;
mod stack_view;
mod text_view;
@ -18,6 +22,7 @@ use stack_view::StackView;
use event::{EventResult,Callback};
/// Identifies a screen in the cursive ROOT.
pub type ScreenId = usize;
/// Central part of the cursive library.
@ -134,35 +139,3 @@ impl Drop for Cursive {
}
}
/// Simple 2D size, in characters.
#[derive(Clone,Copy)]
pub struct Size {
pub w: u32,
pub h: u32,
}
impl Size {
pub fn new(w: u32, h: u32) -> Self {
Size {
w: w,
h: h,
}
}
}
/// A generic trait for converting a value into a 2D size
pub trait ToSize {
fn to_size(self) -> Size;
}
impl ToSize for Size {
fn to_size(self) -> Size {
self
}
}
impl ToSize for (u32,u32) {
fn to_size(self) -> Size {
Size::new(self.0, self.1)
}
}

31
src/printer.rs Normal file
View File

@ -0,0 +1,31 @@
use ncurses;
use vec2::{Vec2,ToVec2};
/// Wrapper around a subset of a ncurses window.
pub struct Printer {
/// ncurses window this printer will use. You can use it directly if you want.
pub win: ncurses::WINDOW,
/// Offset into the window this printer should start drawing at.
pub offset: Vec2,
/// Size of the area we are allowed to draw on.
pub size: Vec2,
}
impl Printer {
/// Prints some text at the given position relative to the window.
pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
let p = pos.to_vec2();
ncurses::mvwprintw(self.win, (p.y + self.offset.y) as i32, (p.x + self.offset.x) as i32, text);
}
/// Returns a printer on a subset of this one's area.
pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S) -> Printer {
let offset_v = offset.to_vec2();
Printer {
win: self.win,
offset: self.offset + offset_v,
// We can't be larger than what remains
size: Vec2::min(self.size - offset_v, size.to_vec2()),
}
}
}

View File

@ -1,10 +1,9 @@
use std::cmp::max;
use ncurses;
use super::Size;
use vec2::Vec2;
use view::{View,SizeRequest};
use event::EventResult;
use printer::Printer;
/// Simple stack of views.
/// Only the top-most view is active and can receive input.
@ -33,10 +32,10 @@ impl StackView {
impl View for StackView {
fn draw(&self, win: ncurses::WINDOW, size: Size) {
fn draw(&self, printer: &Printer) {
match self.layers.last() {
None => (),
Some(v) => v.draw(win, size),
Some(v) => v.draw(printer),
}
}
@ -47,14 +46,14 @@ impl View for StackView {
}
}
fn get_min_size(&self, size: SizeRequest) -> Size {
fn get_min_size(&self, size: SizeRequest) -> Vec2 {
// The min size is the max of all children's
let mut s = Size::new(1,1);
let mut s = Vec2::new(1,1);
for view in self.layers.iter() {
let vs = view.get_min_size(size);
s.w = max(s.w, vs.w);
s.h = max(s.h, vs.h);
s.x = max(s.x, vs.x);
s.y = max(s.y, vs.y);
}
s

View File

@ -1,8 +1,7 @@
use ncurses;
use super::Size;
use vec2::Vec2;
use view::{View,DimensionRequest,SizeRequest};
use div::*;
use printer::Printer;
/// A simple view showing a fixed text
pub struct TextView {
@ -48,19 +47,20 @@ impl TextView {
}
impl View for TextView {
fn draw(&self, win: ncurses::WINDOW, size: Size) {
fn draw(&self, printer: &Printer) {
printer.print((0,0), &self.content);
}
fn get_min_size(&self, size: SizeRequest) -> Size {
fn get_min_size(&self, size: SizeRequest) -> Vec2 {
match (size.w,size.h) {
(DimensionRequest::Unknown, DimensionRequest::Unknown) => Size::new(self.content.len() as u32, 1),
(DimensionRequest::Unknown, DimensionRequest::Unknown) => Vec2::new(self.content.len() as u32, 1),
(DimensionRequest::Fixed(w),_) => {
let h = self.get_num_lines(w as usize) as u32;
Size::new(w, h)
Vec2::new(w, h)
},
(_,DimensionRequest::Fixed(h)) => {
let w = self.get_num_cols(h as usize) as u32;
Size::new(w, h)
Vec2::new(w, h)
},
(DimensionRequest::AtMost(_),DimensionRequest::AtMost(_)) => unreachable!(),
_ => unreachable!(),

68
src/vec2.rs Normal file
View File

@ -0,0 +1,68 @@
use std::ops::{Add, Sub};
use std::cmp::min;
/// Simple 2D size, in characters.
#[derive(Clone,Copy)]
pub struct Vec2 {
/// X coordinate (column), from left to right.
pub x: u32,
/// Y coordinate (row), from top to bottom.
pub y: u32,
}
impl Vec2 {
/// Creates a new Vec2 from coordinates.
pub fn new(x: u32, y: u32) -> Self {
Vec2 {
x: x,
y: y,
}
}
/// Returns a new Vec2 that is no larger than any input in both dimensions.
pub fn min(a: Vec2, b: Vec2) -> Vec2 {
Vec2 {
x: min(a.x, b.x),
y: min(a.y, b.y),
}
}
}
/// A generic trait for converting a value into a 2D vector.
pub trait ToVec2 {
fn to_vec2(self) -> Vec2;
}
impl ToVec2 for Vec2 {
fn to_vec2(self) -> Vec2 {
self
}
}
impl ToVec2 for (u32,u32) {
fn to_vec2(self) -> Vec2 {
Vec2::new(self.0, self.1)
}
}
impl Add for Vec2 {
type Output = Vec2;
fn add(self, other: Vec2) -> Vec2 {
Vec2 {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl Sub for Vec2 {
type Output = Vec2;
fn sub(self, other: Vec2) -> Vec2 {
Vec2 {
x: self.x - other.x,
y: self.y - other.y,
}
}
}

View File

@ -1,12 +1,11 @@
use ncurses;
use event::EventResult;
pub use box_view::BoxView;
pub use stack_view::StackView;
pub use text_view::TextView;
use super::Size;
use vec2::Vec2;
use printer::Printer;
/// Describe constraints on a view layout in one dimension.
#[derive(PartialEq,Clone,Copy)]
@ -34,12 +33,12 @@ pub trait View {
fn on_key_event(&mut self, i32) -> EventResult { EventResult::Ignored }
/// Returns the minimum size the view requires under the given restrictions.
fn get_min_size(&self, SizeRequest) -> Size { Size::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, Size) { }
fn layout(&mut self, Vec2) { }
/// Draws the view within the given bounds.
fn draw(&self, ncurses::WINDOW, Size);
fn draw(&self, &Printer);
}