From 4aaee06d9e3e2274aefeb3a7b36cea175e38afe6 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Tue, 11 Oct 2016 17:12:00 -0700 Subject: [PATCH] Fix screen clear on layer removal Fixes #78. --- src/backend/curses/n.rs | 3 ++- src/event.rs | 9 +++++++++ src/lib.rs | 18 ++++++++++++++---- src/views/menubar.rs | 4 ++-- src/views/stack_view.rs | 14 +++++--------- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/backend/curses/n.rs b/src/backend/curses/n.rs index a22f821..8e8f7a8 100644 --- a/src/backend/curses/n.rs +++ b/src/backend/curses/n.rs @@ -89,7 +89,8 @@ impl backend::Backend for Concrete { // Is it a UTF-8 starting point? if 32 <= ch && ch <= 255 && ch != 127 { - Event::Char(utf8::read_char(ch as u8, || Some(ncurses::getch() as u8)) + Event::Char(utf8::read_char(ch as u8, + || Some(ncurses::getch() as u8)) .unwrap()) } else { parse_ncurses_char(ch) diff --git a/src/event.rs b/src/event.rs index a677789..5d5e349 100644 --- a/src/event.rs +++ b/src/event.rs @@ -78,6 +78,15 @@ impl EventResult { EventResult::Ignored => false, } } + + /// Process this result if it is a callback. + /// + /// Does nothing otherwise. + pub fn process(self, s: &mut Cursive) { + if let EventResult::Consumed(Some(cb)) = self { + cb(s); + } + } } /// A non-character key on the keyboard diff --git a/src/lib.rs b/src/lib.rs index 649c51e..bfbc333 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,10 @@ pub struct Cursive { global_callbacks: HashMap, menubar: views::Menubar, + // Last layer sizes of the stack view. + // If it changed, clear the screen. + last_sizes: Vec, + active_screen: ScreenId, running: bool, @@ -167,6 +171,7 @@ impl Cursive { let mut res = Cursive { theme: theme, screens: Vec::new(), + last_sizes: Vec::new(), global_callbacks: HashMap::new(), menubar: views::Menubar::new(), active_screen: 0, @@ -436,6 +441,7 @@ impl Cursive { /// Convenient method to remove a layer from the current screen. pub fn pop_layer(&mut self) { self.screen_mut().pop_layer(); + self.clear(); } // Handles a key event when it was ignored by the current view @@ -466,6 +472,13 @@ impl Cursive { fn draw(&mut self) { // TODO: don't clone the theme // Reference it or something + + let sizes = self.screen().layer_sizes(); + if &self.last_sizes != &sizes { + self.clear(); + self.last_sizes = sizes; + } + let printer = Printer::new(self.screen_size(), self.theme.clone(), &self.backend); @@ -527,10 +540,7 @@ impl Cursive { // * Current screen (top layer) // * Global callbacks if self.menubar.receive_events() { - if let EventResult::Consumed(Some(cb)) = self.menubar - .on_event(event) { - cb(self); - } + self.menubar.on_event(event).process(self); } else { match self.screen_mut().on_event(event) { // If the event was ignored, diff --git a/src/views/menubar.rs b/src/views/menubar.rs index 6b56638..721dc7c 100644 --- a/src/views/menubar.rs +++ b/src/views/menubar.rs @@ -100,7 +100,7 @@ fn show_child(s: &mut Cursive, offset: (usize, usize), menu: Rc) { s.pop_layer(); s.select_menubar(); // Act as if we sent "Right" then "Down" - s.menubar().on_event(Event::Key(Key::Right)); + s.menubar().on_event(Event::Key(Key::Right)).process(s); if let EventResult::Consumed(Some(cb)) = s.menubar() .on_event(Event::Key(Key::Down)) { cb(s); @@ -110,7 +110,7 @@ fn show_child(s: &mut Cursive, offset: (usize, usize), menu: Rc) { s.pop_layer(); s.select_menubar(); // Act as if we sent "Left" then "Down" - s.menubar().on_event(Event::Key(Key::Left)); + s.menubar().on_event(Event::Key(Key::Left)).process(s); if let EventResult::Consumed(Some(cb)) = s.menubar() .on_event(Event::Key(Key::Down)) { cb(s); diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index 5582d80..e2b93d0 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -13,7 +13,6 @@ use views::ShadowView; pub struct StackView { layers: Vec, last_size: Vec2, - needs_clear: bool, } struct Layer { @@ -32,7 +31,6 @@ impl StackView { StackView { layers: Vec::new(), last_size: Vec2::zero(), - needs_clear: false, } } @@ -58,7 +56,6 @@ impl StackView { /// Remove the top-most layer. pub fn pop_layer(&mut self) { self.layers.pop(); - self.needs_clear = true; } /// Computes the offset of the current top view. @@ -71,13 +68,15 @@ impl StackView { } previous } + + /// Returns the size for each layer in this view. + pub fn layer_sizes(&self) -> Vec { + self.layers.iter().map(|layer| layer.size).collect() + } } 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| { @@ -110,9 +109,6 @@ impl View for StackView { for layer in &mut self.layers { // 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) { - self.needs_clear = true; - } layer.size = size; layer.view.layout(layer.size);