Make Backend::clear take &self

This commit is contained in:
Alexandre Bury 2016-10-09 15:47:06 -07:00
parent a3b5ef3bca
commit 44dbd5826e
6 changed files with 49 additions and 10 deletions

View File

@ -70,7 +70,7 @@ impl backend::Backend for NcursesBackend {
ncurses::attroff(style); ncurses::attroff(style);
} }
fn clear() { fn clear(&self) {
ncurses::clear(); ncurses::clear();
} }

View File

@ -10,7 +10,7 @@ pub trait Backend {
fn init() -> Self; fn init() -> Self;
fn finish(&mut self); fn finish(&mut self);
fn clear(); fn clear(&self);
fn refresh(&self); fn refresh(&self);
fn has_colors(&self) -> bool; fn has_colors(&self) -> bool;

View File

@ -273,7 +273,14 @@ impl Cursive {
pub fn set_theme(&mut self, theme: theme::Theme) { pub fn set_theme(&mut self, theme: theme::Theme) {
self.theme = theme; self.theme = theme;
self.theme.activate(&mut self.backend); self.theme.activate(&mut self.backend);
B::clear(); self.backend.clear();
}
/// Clears the screen.
///
/// If a view becomes smaller, clearing the screen may be necessary.
pub fn clear(&self) {
self.backend.clear();
} }
/// Loads a theme from the given file. /// Loads a theme from the given file.
@ -516,7 +523,7 @@ impl Cursive {
// (If set_fps was called, this returns -1 now and then) // (If set_fps was called, this returns -1 now and then)
let event = self.backend.poll_event(); let event = self.backend.poll_event();
if event == Event::WindowResize { if event == Event::WindowResize {
B::clear(); self.backend.clear();
} }
// Event dispatch order: // Event dispatch order:

View File

@ -3,7 +3,9 @@
use B; use B;
use backend::Backend; use backend::Backend;
use std::cell::Cell;
use std::cmp::min; use std::cmp::min;
use std::rc::Rc;
use theme::{BorderStyle, ColorStyle, Effect, Theme}; use theme::{BorderStyle, ColorStyle, Effect, Theme};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
@ -22,6 +24,9 @@ pub struct Printer<'a> {
/// Currently used theme /// Currently used theme
pub theme: Theme, pub theme: Theme,
/// `true` if nothing has been drawn yet.
new: Rc<Cell<bool>>,
/// Backend used to actually draw things
backend: &'a B, backend: &'a B,
} }
@ -36,14 +41,29 @@ impl<'a> Printer<'a> {
size: size.into(), size: size.into(),
focused: true, focused: true,
theme: theme, theme: theme,
new: Rc::new(Cell::new(true)),
backend: backend, backend: backend,
} }
} }
/// Clear the screen.
///
/// Careful with this method, it will discard anything drawn before.
pub fn clear(&self) {
self.backend.clear();
}
/// Returns `true` if nothing has been printed yet.
pub fn is_new(&self) -> bool {
self.new.get()
}
// TODO: use &mut self? We don't *need* it, but it may make sense. // TODO: use &mut self? We don't *need* it, but it may make sense.
// We don't want people to start calling prints in parallel? // We don't want people to start calling prints in parallel?
/// 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: Into<Vec2>>(&self, pos: S, text: &str) { pub fn print<S: Into<Vec2>>(&self, pos: S, text: &str) {
self.new.set(false);
let p = pos.into(); let p = pos.into();
if p.y >= self.size.y || p.x >= self.size.x { if p.y >= self.size.y || p.x >= self.size.x {
return; return;
@ -61,6 +81,8 @@ impl<'a> Printer<'a> {
/// Prints a vertical line using the given character. /// Prints a vertical line using the given character.
pub fn print_vline<T: Into<Vec2>>(&self, start: T, len: usize, c: &str) { pub fn print_vline<T: Into<Vec2>>(&self, start: T, len: usize, c: &str) {
self.new.set(false);
let p = start.into(); let p = start.into();
if p.y > self.size.y || p.x > self.size.x { if p.y > self.size.y || p.x > self.size.x {
return; return;
@ -75,6 +97,8 @@ impl<'a> Printer<'a> {
/// Prints a horizontal line using the given character. /// Prints a horizontal line using the given character.
pub fn print_hline<T: Into<Vec2>>(&self, start: T, len: usize, c: &str) { pub fn print_hline<T: Into<Vec2>>(&self, start: T, len: usize, c: &str) {
self.new.set(false);
let p = start.into(); let p = start.into();
if p.y > self.size.y || p.x > self.size.x { if p.y > self.size.y || p.x > self.size.x {
return; return;
@ -135,6 +159,8 @@ impl<'a> Printer<'a> {
/// ``` /// ```
pub fn print_box<T: Into<Vec2>, S: Into<Vec2>>(&self, start: T, size: S, pub fn print_box<T: Into<Vec2>, S: Into<Vec2>>(&self, start: T, size: S,
invert: bool) { invert: bool) {
self.new.set(false);
let start = start.into(); let start = start.into();
let size = size.into(); let size = size.into();
if size.x < 2 || size.y < 2 { if size.x < 2 || size.y < 2 {
@ -234,6 +260,7 @@ impl<'a> Printer<'a> {
focused: self.focused && focused, focused: self.focused && focused,
theme: self.theme.clone(), theme: self.theme.clone(),
backend: self.backend, backend: self.backend,
new: self.new.clone(),
} }
} }

View File

@ -1,6 +1,5 @@
use Cursive; use Cursive;
use Printer; use Printer;
use backend::Backend;
use direction; use direction;
use event::*; use event::*;
use menu::MenuTree; use menu::MenuTree;
@ -61,7 +60,6 @@ impl Menubar {
/// Hides the menubar. /// Hides the menubar.
fn hide(&mut self) { fn hide(&mut self) {
self.state = State::Inactive; self.state = State::Inactive;
::B::clear();
} }
/// True if we should be receiving events. /// True if we should be receiving events.
@ -144,7 +142,10 @@ impl View for Menubar {
fn on_event(&mut self, event: Event) -> EventResult { fn on_event(&mut self, event: Event) -> EventResult {
match event { match event {
Event::Key(Key::Esc) => self.hide(), Event::Key(Key::Esc) => {
self.hide();
return EventResult::with_cb(|s| s.clear());
}
Event::Key(Key::Left) => { Event::Key(Key::Left) => {
if self.focus > 0 { if self.focus > 0 {
self.focus -= 1 self.focus -= 1

View File

@ -1,5 +1,4 @@
use Printer; use Printer;
use backend::Backend;
use direction::Direction; use direction::Direction;
use event::{Event, EventResult}; use event::{Event, EventResult};
@ -14,6 +13,7 @@ use views::ShadowView;
pub struct StackView { pub struct StackView {
layers: Vec<Layer>, layers: Vec<Layer>,
last_size: Vec2, last_size: Vec2,
needs_clear: bool,
} }
struct Layer { struct Layer {
@ -32,6 +32,7 @@ impl StackView {
StackView { StackView {
layers: Vec::new(), layers: Vec::new(),
last_size: Vec2::zero(), last_size: Vec2::zero(),
needs_clear: false,
} }
} }
@ -57,7 +58,7 @@ impl StackView {
/// Remove the top-most layer. /// Remove the top-most layer.
pub fn pop_layer(&mut self) { pub fn pop_layer(&mut self) {
self.layers.pop(); self.layers.pop();
::B::clear(); self.needs_clear = true;
} }
/// Computes the offset of the current top view. /// Computes the offset of the current top view.
@ -74,6 +75,9 @@ impl StackView {
impl View for StackView { impl View for StackView {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if self.needs_clear && printer.is_new() {
printer.clear();
}
let last = self.layers.len(); let last = self.layers.len();
let mut previous = Vec2::zero(); let mut previous = Vec2::zero();
printer.with_color(ColorStyle::Primary, |printer| { printer.with_color(ColorStyle::Primary, |printer| {
@ -107,7 +111,7 @@ impl View for StackView {
// Give each guy what he asks for, within the budget constraints. // Give each guy what he asks for, within the budget constraints.
let size = Vec2::min(size, layer.view.get_min_size(size)); let size = Vec2::min(size, layer.view.get_min_size(size));
if !layer.size.fits_in(size) { if !layer.size.fits_in(size) {
::B::clear(); self.needs_clear = true;
} }
layer.size = size; layer.size = size;
layer.view.layout(layer.size); layer.view.layout(layer.size);