diff --git a/src/backend/curses.rs b/src/backend/curses.rs index 1a6a0c9..8cb2303 100644 --- a/src/backend/curses.rs +++ b/src/backend/curses.rs @@ -70,7 +70,7 @@ impl backend::Backend for NcursesBackend { ncurses::attroff(style); } - fn clear() { + fn clear(&self) { ncurses::clear(); } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index f6f243a..63a0f0f 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -10,7 +10,7 @@ pub trait Backend { fn init() -> Self; fn finish(&mut self); - fn clear(); + fn clear(&self); fn refresh(&self); fn has_colors(&self) -> bool; diff --git a/src/lib.rs b/src/lib.rs index a4110c0..5cd310e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -273,7 +273,14 @@ impl Cursive { pub fn set_theme(&mut self, theme: theme::Theme) { self.theme = theme; 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. @@ -516,7 +523,7 @@ impl Cursive { // (If set_fps was called, this returns -1 now and then) let event = self.backend.poll_event(); if event == Event::WindowResize { - B::clear(); + self.backend.clear(); } // Event dispatch order: diff --git a/src/printer.rs b/src/printer.rs index 2f846f6..ff71627 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -3,7 +3,9 @@ use B; use backend::Backend; +use std::cell::Cell; use std::cmp::min; +use std::rc::Rc; use theme::{BorderStyle, ColorStyle, Effect, Theme}; use unicode_segmentation::UnicodeSegmentation; @@ -22,6 +24,9 @@ pub struct Printer<'a> { /// Currently used theme pub theme: Theme, + /// `true` if nothing has been drawn yet. + new: Rc>, + /// Backend used to actually draw things backend: &'a B, } @@ -36,14 +41,29 @@ impl<'a> Printer<'a> { size: size.into(), focused: true, theme: theme, + new: Rc::new(Cell::new(true)), 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. // We don't want people to start calling prints in parallel? /// Prints some text at the given position relative to the window. pub fn print>(&self, pos: S, text: &str) { + self.new.set(false); + let p = pos.into(); if p.y >= self.size.y || p.x >= self.size.x { return; @@ -61,6 +81,8 @@ impl<'a> Printer<'a> { /// Prints a vertical line using the given character. pub fn print_vline>(&self, start: T, len: usize, c: &str) { + self.new.set(false); + let p = start.into(); if p.y > self.size.y || p.x > self.size.x { return; @@ -75,6 +97,8 @@ impl<'a> Printer<'a> { /// Prints a horizontal line using the given character. pub fn print_hline>(&self, start: T, len: usize, c: &str) { + self.new.set(false); + let p = start.into(); if p.y > self.size.y || p.x > self.size.x { return; @@ -135,6 +159,8 @@ impl<'a> Printer<'a> { /// ``` pub fn print_box, S: Into>(&self, start: T, size: S, invert: bool) { + self.new.set(false); + let start = start.into(); let size = size.into(); if size.x < 2 || size.y < 2 { @@ -234,6 +260,7 @@ impl<'a> Printer<'a> { focused: self.focused && focused, theme: self.theme.clone(), backend: self.backend, + new: self.new.clone(), } } diff --git a/src/views/menubar.rs b/src/views/menubar.rs index 48198a1..6b56638 100644 --- a/src/views/menubar.rs +++ b/src/views/menubar.rs @@ -1,6 +1,5 @@ use Cursive; use Printer; -use backend::Backend; use direction; use event::*; use menu::MenuTree; @@ -61,7 +60,6 @@ impl Menubar { /// Hides the menubar. fn hide(&mut self) { self.state = State::Inactive; - ::B::clear(); } /// True if we should be receiving events. @@ -144,7 +142,10 @@ impl View for Menubar { fn on_event(&mut self, event: Event) -> EventResult { 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) => { if self.focus > 0 { self.focus -= 1 diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index 0014eef..5582d80 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -1,5 +1,4 @@ use Printer; -use backend::Backend; use direction::Direction; use event::{Event, EventResult}; @@ -14,6 +13,7 @@ use views::ShadowView; pub struct StackView { layers: Vec, last_size: Vec2, + needs_clear: bool, } struct Layer { @@ -32,6 +32,7 @@ impl StackView { StackView { layers: Vec::new(), last_size: Vec2::zero(), + needs_clear: false, } } @@ -57,7 +58,7 @@ impl StackView { /// Remove the top-most layer. pub fn pop_layer(&mut self) { self.layers.pop(); - ::B::clear(); + self.needs_clear = true; } /// Computes the offset of the current top view. @@ -74,6 +75,9 @@ impl StackView { impl View for StackView { fn draw(&self, printer: &Printer) { + if self.needs_clear && printer.is_new() { + printer.clear(); + } let last = self.layers.len(); let mut previous = Vec2::zero(); 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. let size = Vec2::min(size, layer.view.get_min_size(size)); if !layer.size.fits_in(size) { - ::B::clear(); + self.needs_clear = true; } layer.size = size; layer.view.layout(layer.size);