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() { fn main() {
let mut siv = Cursive::new(); 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!")) siv.add_layer(Dialog::new(TextView::new("Tak!"))
.button("Change", |s,_| s.find::<TextView>(&Selector::Id("text")).unwrap() .button("Change", |s,_| s.find::<TextView>(&Selector::Id("text")).unwrap()
.set_content("Bleeeeh") )); .set_content("Bleeeeh\nBleeeeeeeeeeh\nBleeeh") )
.dismiss_button("Ok"));
siv.run(); siv.run();
} }

View File

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

View File

@ -5,50 +5,18 @@ use ncurses;
use color; use color;
use vec::{Vec2,ToVec2}; 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 { 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. /// Offset into the window this printer should start drawing at.
pub offset: Vec2, pub offset: Vec2,
/// Size of the area we are allowed to draw on. /// Size of the area we are allowed to draw on.
pub size: Vec2, 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 { impl Printer {
/// Creates a new printer on the given window. /// 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 { Printer {
win: win,
offset: Vec2::zero(), offset: Vec2::zero(),
size: size.to_vec2(), size: size.to_vec2(),
} }
@ -57,28 +25,30 @@ impl Printer {
/// Prints some text at the given position relative to the window. /// Prints some text at the given position relative to the window.
pub fn print<S: ToVec2>(&self, pos: S, text: &str) { pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
let p = pos.to_vec2() + self.offset; 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. /// Prints a vertical line using the given character.
pub fn print_vline<T: ToVec2>(&self, start: T, len: u32, c: u64) { pub fn print_vline<T: ToVec2>(&self, start: T, len: u32, c: u64) {
let p = start.to_vec2() + self.offset; 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. /// Prints a horizontal line using the given character.
pub fn print_hline<T: ToVec2>(&self, start: T, len: u32, c: u64) { pub fn print_hline<T: ToVec2>(&self, start: T, len: u32, c: u64) {
let p = start.to_vec2() + self.offset; 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, /// Returns a wrapper around this printer,
/// that will apply the given style on prints. /// that will apply the given style on prints.
pub fn style<'a>(&'a self, style: color::ThemeColor) -> StyledPrinter<'a> { pub fn with_style<'a, F>(&'a self, style: color::ThemeColor, f: F)
StyledPrinter { where F: Fn(&Printer)
parent: self, {
style: style, 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. /// Prints a rectangular box.
@ -92,8 +62,6 @@ impl Printer {
let start_v = start.to_vec2(); 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, "");
self.print(start_v + size_v.keep_x(), ""); self.print(start_v + size_v.keep_x(), "");
self.print(start_v + size_v.keep_y(), ""); 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 { pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S) -> Printer {
let offset_v = offset.to_vec2(); let offset_v = offset.to_vec2();
Printer { Printer {
win: self.win,
offset: self.offset + offset_v, offset: self.offset + offset_v,
// We can't be larger than what remains // We can't be larger than what remains
size: Vec2::min(self.size - offset_v, size.to_vec2()), 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 style = if !focused { color::PRIMARY } else { color::HIGHLIGHT };
let x = printer.size.x - 1; let x = printer.size.x - 1;
let printer = printer.style(style); printer.with_style(style, |printer| {
printer.print((1u32,0u32), &self.label); printer.print((1u32,0u32), &self.label);
printer.print((0u32,0u32), "<"); printer.print((0u32,0u32), "<");
printer.print((x,0), ">"); printer.print((x,0), ">");
});
} }
fn get_min_size(&self, _: SizeRequest) -> Vec2 { 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-2,0), "");
printer.print((x+self.title.len() as u32,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 sized_view;
mod full_view; mod full_view;
mod id_view; mod id_view;
mod shadow_view;
use std::any::Any; use std::any::Any;
@ -25,6 +26,7 @@ pub use self::sized_view::SizedView;
pub use self::view_wrapper::ViewWrapper; pub use self::view_wrapper::ViewWrapper;
pub use self::full_view::FullView; pub use self::full_view::FullView;
pub use self::id_view::IdView; pub use self::id_view::IdView;
pub use self::shadow_view::ShadowView;
use event::EventResult; use event::EventResult;
use vec::{Vec2,ToVec2}; 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::cmp::max;
use std::any::Any; use std::any::Any;
use ncurses;
use color; use color;
use vec::Vec2; use vec::Vec2;
use view::{View,SizeRequest,DimensionRequest,Selector}; use view::{View,SizeRequest,DimensionRequest,Selector,ShadowView};
use event::EventResult; use event::EventResult;
use printer::Printer; use printer::Printer;
@ -18,7 +16,6 @@ pub struct StackView {
struct Layer { struct Layer {
view: Box<View>, view: Box<View>,
size: Vec2, size: Vec2,
win: Option<ncurses::WINDOW>,
} }
impl StackView { impl StackView {
@ -32,9 +29,8 @@ impl StackView {
/// Add new view on top of the stack. /// Add new view on top of the stack.
pub fn add_layer<T: 'static + View>(&mut self, view: T) { pub fn add_layer<T: 'static + View>(&mut self, view: T) {
self.layers.push(Layer { self.layers.push(Layer {
view: Box::new(view), view: Box::new(ShadowView::new(view)),
size: Vec2::new(0,0), size: Vec2::new(0,0),
win: None,
}); });
} }
@ -44,26 +40,17 @@ impl StackView {
} }
} }
impl View for StackView { impl View for StackView {
fn draw(&mut self, printer: &Printer, focused: bool) { fn draw(&mut self, printer: &Printer, focused: bool) {
ncurses::wrefresh(printer.win);
for v in self.layers.iter_mut() { for v in self.layers.iter_mut() {
// Center the view // Center the view
v.view.draw(&Printer::new(v.win.unwrap(), v.size), focused); let size = v.size;
let offset = (printer.size - size) / 2;
let h = v.size.y; v.view.draw(&printer.sub_printer(offset, size), focused);
let w = v.size.x;
let x = (printer.size.x - w) / 2;
let y = (printer.size.y - h) / 2;
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); // 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 w = layer.size.x as i32;
let x = (size.x as i32 - w) / 2; let x = (size.x as i32 - w) / 2;
let y = (size.y as i32 - h) / 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);
} }
} }