Stop using ncurses::WINDOW

Overlap is a mess. Let's do it ourselve.
This commit is contained in:
Alexandre Bury 2015-05-23 15:58:06 -07:00
parent d9b56574d2
commit 7e823435cd
8 changed files with 84 additions and 79 deletions

View File

@ -6,11 +6,14 @@ use cursive::view::{IdView,TextView,Dialog,Selector};
fn main() {
let mut siv = Cursive::new();
siv.add_layer(IdView::new("text", TextView::new("Aaahh\nAaaah\nAaaah\nAaaaah\nAaaaah\nAaaaah\nAaaaah")));
siv.add_global_callback('q' as i32, |s,_| s.quit());
siv.add_layer(IdView::new("text", TextView::new("Aaahh\nAaaah\nAaaah\nAaaaah\nAaaaah\nAaaaah\nAaaaah\nAaaaaah\nAaaaah")));
siv.add_layer(Dialog::new(TextView::new("Tak!"))
.button("Change", |s,_| s.find::<TextView>(&Selector::Id("text")).unwrap()
.set_content("Bleeeeh") ));
.set_content("Bleeeeh\nBleeeeeeeeeeh\nBleeeh") )
.dismiss_button("Ok"));
siv.run();
}

View File

@ -188,11 +188,11 @@ impl Cursive {
fn draw(&mut self) {
let printer = Printer {
win: ncurses::stdscr,
offset: Vec2::new(0,0),
size: self.screen_size(),
};
self.screen_mut().draw(&printer, true);
ncurses::refresh();
}
/// Runs the event loop.

View File

@ -5,50 +5,18 @@ use ncurses;
use color;
use vec::{Vec2,ToVec2};
/// Wrapper around a subset of a ncurses window.
/// Convenient interface to draw on a subset of the screen.
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,
}
/// Wrapper around a parent printer that applies a style to prints.
pub struct StyledPrinter<'a> {
parent: &'a Printer,
style: color::ThemeColor,
}
impl <'a> StyledPrinter<'a> {
/// Wrapper around the parent's `print` method with `self.style` applied.
pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
ncurses::wattron(self.parent.win, ncurses::COLOR_PAIR(self.style) as i32);
self.parent.print(pos, text);
ncurses::wattroff(self.parent.win, ncurses::COLOR_PAIR(self.style) as i32);
}
/// Wrapper around the parent's `print_vline` method with `self.style` applied.
pub fn print_vline<T: ToVec2>(&self, start: T, len: u32, c: u64) {
ncurses::wattron(self.parent.win, ncurses::COLOR_PAIR(self.style) as i32);
self.parent.print_vline(start, len, c);
ncurses::wattroff(self.parent.win, ncurses::COLOR_PAIR(self.style) as i32);
}
/// Wrapper around the parent's `print_hline` method with `self.style` applied.
pub fn print_hline<T: ToVec2>(&self, start: T, len: u32, c: u64) {
ncurses::wattron(self.parent.win, ncurses::COLOR_PAIR(self.style) as i32);
self.parent.print_hline(start, len, c);
ncurses::wattroff(self.parent.win, ncurses::COLOR_PAIR(self.style) as i32);
}
}
impl Printer {
/// Creates a new printer on the given window.
pub fn new<T: ToVec2>(win: ncurses::WINDOW, size: T) -> Self {
pub fn new<T: ToVec2>(size: T) -> Self {
Printer {
win: win,
offset: Vec2::zero(),
size: size.to_vec2(),
}
@ -57,28 +25,30 @@ 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() + self.offset;
ncurses::mvwprintw(self.win, p.y as i32, p.x as i32, text);
ncurses::mvprintw(p.y as i32, p.x as i32, text);
}
/// Prints a vertical line using the given character.
pub fn print_vline<T: ToVec2>(&self, start: T, len: u32, c: u64) {
let p = start.to_vec2() + self.offset;
ncurses::mvwvline(self.win, p.y as i32, p.x as i32, c, len as i32);
ncurses::mvvline(p.y as i32, p.x as i32, c, len as i32);
}
/// Prints a horizontal line using the given character.
pub fn print_hline<T: ToVec2>(&self, start: T, len: u32, c: u64) {
let p = start.to_vec2() + self.offset;
ncurses::mvwhline(self.win, p.y as i32, p.x as i32, c, len as i32);
ncurses::mvhline(p.y as i32, p.x as i32, c, len as i32);
}
/// Returns a wrapper around this printer,
/// that will apply the given style on prints.
pub fn style<'a>(&'a self, style: color::ThemeColor) -> StyledPrinter<'a> {
StyledPrinter {
parent: self,
style: style,
}
pub fn with_style<'a, F>(&'a self, style: color::ThemeColor, f: F)
where F: Fn(&Printer)
{
ncurses::attron(ncurses::COLOR_PAIR(style));
f(self);
ncurses::attroff(ncurses::COLOR_PAIR(style));
ncurses::attron(ncurses::COLOR_PAIR(color::PRIMARY));
}
/// Prints a rectangular box.
@ -92,8 +62,6 @@ impl Printer {
let start_v = start.to_vec2();
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(), "");
@ -109,7 +77,6 @@ impl Printer {
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

@ -32,10 +32,11 @@ impl View for Button {
let style = if !focused { color::PRIMARY } else { color::HIGHLIGHT };
let x = printer.size.x - 1;
let printer = printer.style(style);
printer.with_style(style, |printer| {
printer.print((1u32,0u32), &self.label);
printer.print((0u32,0u32), "<");
printer.print((x,0), ">");
});
}
fn get_min_size(&self, _: SizeRequest) -> Vec2 {

View File

@ -106,7 +106,7 @@ impl View for Dialog {
printer.print((x-2,0), "");
printer.print((x+self.title.len() as u32,0), "");
printer.style(color::TITLE_PRIMARY).print((x,0), &self.title);
printer.with_style(color::TITLE_PRIMARY, |p| p.print((x,0), &self.title));
}
}

View File

@ -11,6 +11,7 @@ mod button;
mod sized_view;
mod full_view;
mod id_view;
mod shadow_view;
use std::any::Any;
@ -25,6 +26,7 @@ pub use self::sized_view::SizedView;
pub use self::view_wrapper::ViewWrapper;
pub use self::full_view::FullView;
pub use self::id_view::IdView;
pub use self::shadow_view::ShadowView;
use event::EventResult;
use vec::{Vec2,ToVec2};

53
src/view/shadow_view.rs Normal file
View File

@ -0,0 +1,53 @@
use view::{View,ViewWrapper,SizeRequest};
use printer::Printer;
use vec::Vec2;
use color;
pub struct ShadowView<T: View> {
pub view: T,
}
impl <T: View> ShadowView<T> {
pub fn new(view: T) -> Self {
ShadowView {
view: view,
}
}
}
impl <T: View> ViewWrapper for ShadowView<T> {
wrap_impl!(&self.view);
fn wrap_get_min_size(&self, req: SizeRequest) -> Vec2 {
self.view.get_min_size(req.reduced((2,2))) + (2,2)
}
fn wrap_layout(&mut self, size: Vec2) {
self.view.layout(size - (2,2));
}
fn wrap_draw(&mut self, printer: &Printer, focused: bool) {
{
printer.with_style(color::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);
}
});
}
self.view.draw(&printer.sub_printer(Vec2::new(1,1), printer.size - (2,2)), focused);
let h = printer.size.y-1;
let w = printer.size.x-1;
printer.with_style(color::SHADOW, |printer| {
printer.print_hline((2,h), w-1, ' ' as u64);
printer.print_vline((w,2), h-1, ' ' as u64);
});
}
}

View File

@ -1,11 +1,9 @@
use std::cmp::max;
use std::any::Any;
use ncurses;
use color;
use vec::Vec2;
use view::{View,SizeRequest,DimensionRequest,Selector};
use view::{View,SizeRequest,DimensionRequest,Selector,ShadowView};
use event::EventResult;
use printer::Printer;
@ -18,7 +16,6 @@ pub struct StackView {
struct Layer {
view: Box<View>,
size: Vec2,
win: Option<ncurses::WINDOW>,
}
impl StackView {
@ -32,9 +29,8 @@ impl StackView {
/// Add new view on top of the stack.
pub fn add_layer<T: 'static + View>(&mut self, view: T) {
self.layers.push(Layer {
view: Box::new(view),
view: Box::new(ShadowView::new(view)),
size: Vec2::new(0,0),
win: None,
});
}
@ -44,26 +40,17 @@ impl StackView {
}
}
impl View for StackView {
fn draw(&mut self, printer: &Printer, focused: bool) {
ncurses::wrefresh(printer.win);
for v in self.layers.iter_mut() {
// Center the view
v.view.draw(&Printer::new(v.win.unwrap(), v.size), focused);
let h = v.size.y;
let w = v.size.x;
let x = (printer.size.x - w) / 2;
let y = (printer.size.y - h) / 2;
let size = v.size;
let offset = (printer.size - size) / 2;
v.view.draw(&printer.sub_printer(offset, size), focused);
let printer = printer.style(color::HIGHLIGHT);
printer.print_hline((x+1,y+h), w, ' ' as u64);
printer.print_vline((x+w,y+1), h, ' ' as u64);
// v.view.draw(&printer.sub_printer(offset, v.size), focused);
ncurses::wrefresh(v.win.unwrap());
}
}
@ -87,14 +74,6 @@ impl View for StackView {
let w = layer.size.x as i32;
let x = (size.x as i32 - w) / 2;
let y = (size.y as i32 - h) / 2;
let win = ncurses::newwin(h, w, y, x);
ncurses::wbkgd(win, ncurses::COLOR_PAIR(color::PRIMARY));
match layer.win {
None => (),
Some(w) => { ncurses::delwin(w); },
}
layer.win = Some(win);
}
}