Making backend::Backend into a std::Boxable trait (#229)

* Making Backend into a Boxable Trait

* Fixed up some typos in the previous and modified some of the docs so they still compile.

* Minor Changes requested by @gyscos

* Whoops
This commit is contained in:
SEGFAULT 2018-04-02 00:35:37 +02:00 committed by Alexandre Bury
parent 8c64ea0101
commit 76d340f11d
8 changed files with 105 additions and 60 deletions

View File

@ -145,7 +145,7 @@ impl Concrete {
} }
impl backend::Backend for Concrete { impl backend::Backend for Concrete {
fn init() -> Self { fn init() -> Box<Self> {
terminal::open("Cursive", 80, 24); terminal::open("Cursive", 80, 24);
terminal::set(terminal::config::Window::empty().resizeable(true)); terminal::set(terminal::config::Window::empty().resizeable(true));
terminal::set(vec![ terminal::set(vec![
@ -159,37 +159,59 @@ impl backend::Backend for Concrete {
}, },
]); ]);
Concrete { let c = Concrete {
mouse_position: Vec2::zero(), mouse_position: Vec2::zero(),
buttons_pressed: HashSet::new(), buttons_pressed: HashSet::new(),
} };
Box::new(c)
} }
fn finish(&mut self) { fn finish(&mut self) {
terminal::close(); terminal::close();
} }
fn with_color<F: FnOnce()>(&self, color: ColorPair, f: F) { fn set_color(&self, color: ColorPair) -> ColorPair {
let current = ColorPair {
front: blt_colour_to_colour(state::foreground()),
back: blt_colour_to_colour(state::background())
};
let fg = colour_to_blt_colour(color.front, ColorRole::Foreground); let fg = colour_to_blt_colour(color.front, ColorRole::Foreground);
let bg = colour_to_blt_colour(color.back, ColorRole::Background); let bg = colour_to_blt_colour(color.back, ColorRole::Background);
terminal::with_colors(fg, bg, f);
terminal::set_colors(fg, bg);
current
} }
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) { fn set_effect(&self, effect: Effect) {
match effect { match effect {
// TODO: does BLT support bold/italic/underline? // TODO: does BLT support bold/italic/underline?
Effect::Bold Effect::Bold
| Effect::Italic | Effect::Italic
| Effect::Underline | Effect::Underline
| Effect::Simple => f(), | Effect::Simple => {},
// TODO: how to do this correctly?` // TODO: how to do this correctly?`
// BLT itself doesn't do this kind of thing, // BLT itself doesn't do this kind of thing,
// we'd need the colours in our position, // we'd need the colours in our position,
// but `f()` can do whatever // but `f()` can do whatever
Effect::Reverse => terminal::with_colors( Effect::Reverse => terminal::set_colors(
BltColor::from_rgb(0, 0, 0), state::background(), state::foreground()
BltColor::from_rgb(255, 255, 255), ),
f, }
}
fn unset_effect(&self, effect: Effect) {
match effect {
// TODO: does BLT support bold/italic/underline?
Effect::Bold
| Effect::Italic
| Effect::Underline
| Effect::Simple => {},
// The process of reversing is the same as unreversing
Effect::Reverse => terminal::set_colors(
state::background(), state::foreground()
), ),
} }
} }
@ -282,6 +304,10 @@ impl backend::Backend for Concrete {
} }
} }
fn blt_colour_to_colour(c: BltColor) -> Color {
Color::Rgb(c.red, c.green, c.blue)
}
fn colour_to_blt_colour(clr: Color, role: ColorRole) -> BltColor { fn colour_to_blt_colour(clr: Color, role: ColorRole) -> BltColor {
let (r, g, b) = match clr { let (r, g, b) = match clr {
Color::TerminalDefault => { Color::TerminalDefault => {

View File

@ -150,7 +150,7 @@ impl Concrete {
} }
impl backend::Backend for Concrete { impl backend::Backend for Concrete {
fn init() -> Self { fn init() -> Box<Self> {
// Change the locale. // Change the locale.
// For some reasons it's mandatory to get some UTF-8 support. // For some reasons it's mandatory to get some UTF-8 support.
ncurses::setlocale(ncurses::LcCategory::all, ""); ncurses::setlocale(ncurses::LcCategory::all, "");
@ -186,7 +186,7 @@ impl backend::Backend for Concrete {
print!("\x1B[?1002h"); print!("\x1B[?1002h");
stdout().flush().expect("could not flush stdout"); stdout().flush().expect("could not flush stdout");
Concrete { let c = Concrete {
current_style: Cell::new(ColorPair::from_256colors(0, 0)), current_style: Cell::new(ColorPair::from_256colors(0, 0)),
pairs: RefCell::new(HashMap::new()), pairs: RefCell::new(HashMap::new()),
@ -194,7 +194,9 @@ impl backend::Backend for Concrete {
event_queue: Vec::new(), event_queue: Vec::new(),
key_codes: initialize_keymap(), key_codes: initialize_keymap(),
} };
Box::new(c)
} }
fn screen_size(&self) -> (usize, usize) { fn screen_size(&self) -> (usize, usize) {
@ -214,21 +216,16 @@ impl backend::Backend for Concrete {
ncurses::endwin(); ncurses::endwin();
} }
fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) { fn set_color(&self, colors: ColorPair) -> ColorPair {
// eprintln!("Color used: {:?}", colors); // eprintln!("Color used: {:?}", colors);
let current = self.current_style.get(); let current = self.current_style.get();
if current != colors { if current != colors {
self.set_colors(colors); self.set_colors(colors);
} }
return current;
f();
if current != colors {
self.set_colors(current);
}
} }
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) { fn set_effect(&self, effect: Effect) {
let style = match effect { let style = match effect {
Effect::Reverse => ncurses::A_REVERSE(), Effect::Reverse => ncurses::A_REVERSE(),
Effect::Simple => ncurses::A_NORMAL(), Effect::Simple => ncurses::A_NORMAL(),
@ -237,7 +234,16 @@ impl backend::Backend for Concrete {
Effect::Underline => ncurses::A_UNDERLINE(), Effect::Underline => ncurses::A_UNDERLINE(),
}; };
ncurses::attron(style); ncurses::attron(style);
f(); }
fn unset_effect(&self, effect: Effect) {
let style = match effect {
Effect::Reverse => ncurses::A_REVERSE(),
Effect::Simple => ncurses::A_NORMAL(),
Effect::Bold => ncurses::A_BOLD(),
Effect::Italic => ncurses::A_ITALIC(),
Effect::Underline => ncurses::A_UNDERLINE(),
};
ncurses::attroff(style); ncurses::attroff(style);
} }

View File

@ -133,7 +133,7 @@ impl Concrete {
} }
impl backend::Backend for Concrete { impl backend::Backend for Concrete {
fn init() -> Self { fn init() -> Box<Self> {
::std::env::set_var("ESCDELAY", "25"); ::std::env::set_var("ESCDELAY", "25");
let window = pancurses::initscr(); let window = pancurses::initscr();
@ -155,14 +155,16 @@ impl backend::Backend for Concrete {
print!("\x1B[?1002h"); print!("\x1B[?1002h");
stdout().flush().expect("could not flush stdout"); stdout().flush().expect("could not flush stdout");
Concrete { let c = Concrete {
current_style: Cell::new(ColorPair::from_256colors(0, 0)), current_style: Cell::new(ColorPair::from_256colors(0, 0)),
pairs: RefCell::new(HashMap::new()), pairs: RefCell::new(HashMap::new()),
window: window, window: window,
last_mouse_button: None, last_mouse_button: None,
event_queue: Vec::new(), event_queue: Vec::new(),
key_codes: initialize_keymap(), key_codes: initialize_keymap(),
} };
Box::new(c)
} }
fn screen_size(&self) -> (usize, usize) { fn screen_size(&self) -> (usize, usize) {
@ -180,21 +182,17 @@ impl backend::Backend for Concrete {
pancurses::endwin(); pancurses::endwin();
} }
fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) { fn set_color(&self, colors: ColorPair) -> ColorPair {
let current = self.current_style.get(); let current = self.current_style.get();
if current != colors { if current != colors {
self.set_colors(colors); self.set_colors(colors);
} }
f(); current
if current != colors {
self.set_colors(current);
}
} }
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) { fn set_effect(&self, effect: Effect) {
let style = match effect { let style = match effect {
Effect::Simple => pancurses::Attribute::Normal, Effect::Simple => pancurses::Attribute::Normal,
Effect::Reverse => pancurses::Attribute::Reverse, Effect::Reverse => pancurses::Attribute::Reverse,
@ -203,7 +201,16 @@ impl backend::Backend for Concrete {
Effect::Underline => pancurses::Attribute::Underline, Effect::Underline => pancurses::Attribute::Underline,
}; };
self.window.attron(style); self.window.attron(style);
f(); }
fn unset_effect(&self, effect: Effect) {
let style = match effect {
Effect::Simple => pancurses::Attribute::Normal,
Effect::Reverse => pancurses::Attribute::Reverse,
Effect::Bold => pancurses::Attribute::Bold,
Effect::Italic => pancurses::Attribute::Italic,
Effect::Underline => pancurses::Attribute::Underline,
};
self.window.attroff(style); self.window.attroff(style);
} }

View File

@ -16,7 +16,7 @@ pub use self::curses::*;
pub use self::termion::*; pub use self::termion::*;
pub trait Backend { pub trait Backend {
fn init() -> Self; fn init() -> Box<Self> where Self: Sized;
// TODO: take `self` by value? // TODO: take `self` by value?
// Or implement Drop? // Or implement Drop?
fn finish(&mut self); fn finish(&mut self);
@ -34,7 +34,11 @@ pub trait Backend {
fn clear(&self, color: theme::Color); fn clear(&self, color: theme::Color);
fn set_refresh_rate(&mut self, fps: u32); fn set_refresh_rate(&mut self, fps: u32);
// TODO: unify those into a single method?
fn with_color<F: FnOnce()>(&self, colors: theme::ColorPair, f: F); // This sets the Colours and returns the previous colours
fn with_effect<F: FnOnce()>(&self, effect: theme::Effect, f: F); // to allow you to set them back when you're done.
fn set_color(&self, colors: theme::ColorPair) -> theme::ColorPair;
fn set_effect(&self, effect: theme::Effect);
fn unset_effect(&self, effect: theme::Effect);
} }

View File

@ -137,7 +137,7 @@ impl Concrete {
} }
impl backend::Backend for Concrete { impl backend::Backend for Concrete {
fn init() -> Self { fn init() -> Box<Self> {
print!("{}", termion::cursor::Hide); print!("{}", termion::cursor::Hide);
let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]); let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]);
@ -157,14 +157,16 @@ impl backend::Backend for Concrete {
} }
}); });
Concrete { let c = Concrete {
terminal: terminal, terminal: terminal,
current_style: Cell::new(theme::ColorPair::from_256colors(0, 0)), current_style: Cell::new(theme::ColorPair::from_256colors(0, 0)),
input: receiver, input: receiver,
resize: resize, resize: resize,
timeout: None, timeout: None,
last_button: None, last_button: None,
} };
Box::new(c)
} }
fn finish(&mut self) { fn finish(&mut self) {
@ -177,7 +179,7 @@ impl backend::Backend for Concrete {
); );
} }
fn with_color<F: FnOnce()>(&self, color: theme::ColorPair, f: F) { fn set_color(&self, color: theme::ColorPair) -> theme::ColorPair {
let current_style = self.current_style.get(); let current_style = self.current_style.get();
if current_style != color { if current_style != color {
@ -185,17 +187,14 @@ impl backend::Backend for Concrete {
self.current_style.set(color); self.current_style.set(color);
} }
f(); return current_style;
if current_style != color {
self.current_style.set(current_style);
self.apply_colors(current_style);
}
} }
fn with_effect<F: FnOnce()>(&self, effect: theme::Effect, f: F) { fn set_effect(&self, effect: theme::Effect) {
effect.on(); effect.on();
f(); }
fn unset_effect(&self, effect: theme::Effect) {
effect.off(); effect.off();
} }

View File

@ -54,7 +54,7 @@ pub struct Cursive {
running: bool, running: bool,
backend: backend::Concrete, backend: Box<backend::Backend>,
cb_source: mpsc::Receiver<Box<CbFunc>>, cb_source: mpsc::Receiver<Box<CbFunc>>,
cb_sink: mpsc::Sender<Box<CbFunc>>, cb_sink: mpsc::Sender<Box<CbFunc>>,

View File

@ -1,6 +1,6 @@
//! Makes drawing on ncurses windows easier. //! Makes drawing on ncurses windows easier.
use backend::{self, Backend}; use backend::Backend;
use enumset::EnumSet; use enumset::EnumSet;
use std::cell::Cell; use std::cell::Cell;
use std::cmp::min; use std::cmp::min;
@ -24,7 +24,7 @@ pub struct Printer<'a> {
/// `true` if nothing has been drawn yet. /// `true` if nothing has been drawn yet.
new: Rc<Cell<bool>>, new: Rc<Cell<bool>>,
/// Backend used to actually draw things /// Backend used to actually draw things
backend: &'a backend::Concrete, backend: &'a Box<Backend>,
} }
impl<'a> Printer<'a> { impl<'a> Printer<'a> {
@ -33,7 +33,7 @@ impl<'a> Printer<'a> {
/// But nobody needs to know that. /// But nobody needs to know that.
#[doc(hidden)] #[doc(hidden)]
pub fn new<T: Into<Vec2>>( pub fn new<T: Into<Vec2>>(
size: T, theme: &'a Theme, backend: &'a backend::Concrete size: T, theme: &'a Theme, backend: &'a Box<Backend>
) -> Self { ) -> Self {
Printer { Printer {
offset: Vec2::zero(), offset: Vec2::zero(),
@ -121,7 +121,7 @@ impl<'a> Printer<'a> {
/// # use cursive::Printer; /// # use cursive::Printer;
/// # use cursive::theme; /// # use cursive::theme;
/// # use cursive::backend::{self, Backend}; /// # use cursive::backend::{self, Backend};
/// # let b = backend::Concrete::init(); /// # let b: Box<Backend> = backend::Concrete::init();
/// # let t = theme::load_default(); /// # let t = theme::load_default();
/// # let printer = Printer::new((6,4), &t, &b); /// # let printer = Printer::new((6,4), &t, &b);
/// printer.with_color(theme::ColorStyle::highlight(), |printer| { /// printer.with_color(theme::ColorStyle::highlight(), |printer| {
@ -132,8 +132,9 @@ impl<'a> Printer<'a> {
where where
F: FnOnce(&Printer), F: FnOnce(&Printer),
{ {
self.backend let old = self.backend.set_color(c.resolve(&self.theme.palette));
.with_color(c.resolve(&self.theme.palette), || f(self)); f(self);
self.backend.set_color(old);
} }
/// Call the given closure with a styled printer, /// Call the given closure with a styled printer,
@ -165,7 +166,9 @@ impl<'a> Printer<'a> {
where where
F: FnOnce(&Printer), F: FnOnce(&Printer),
{ {
self.backend.with_effect(effect, || f(self)); self.backend.set_effect(effect);
f(self);
self.backend.unset_effect(effect);
} }
/// Call the given closure with a modified printer /// Call the given closure with a modified printer
@ -196,7 +199,7 @@ impl<'a> Printer<'a> {
/// # use cursive::Printer; /// # use cursive::Printer;
/// # use cursive::theme; /// # use cursive::theme;
/// # use cursive::backend::{self, Backend}; /// # use cursive::backend::{self, Backend};
/// # let b = backend::Concrete::init(); /// # let b: Box<Backend> = backend::Concrete::init();
/// # let t = theme::load_default(); /// # let t = theme::load_default();
/// # let printer = Printer::new((6,4), &t, &b); /// # let printer = Printer::new((6,4), &t, &b);
/// printer.print_box((0,0), (6,4), false); /// printer.print_box((0,0), (6,4), false);

View File

@ -232,7 +232,7 @@ impl ScrollBase {
/// # use cursive::theme; /// # use cursive::theme;
/// # use cursive::backend::{self, Backend}; /// # use cursive::backend::{self, Backend};
/// # let scrollbase = ScrollBase::new(); /// # let scrollbase = ScrollBase::new();
/// # let b = backend::Concrete::init(); /// # let b: Box<Backend> = backend::Concrete::init();
/// # let t = theme::load_default(); /// # let t = theme::load_default();
/// # let printer = Printer::new((5,1), &t, &b); /// # let printer = Printer::new((5,1), &t, &b);
/// # let printer = &printer; /// # let printer = &printer;