Fix screen clear on layer removal

Fixes #78.
This commit is contained in:
Alexandre Bury 2016-10-11 17:12:00 -07:00
parent b43b6c4700
commit 4aaee06d9e
5 changed files with 32 additions and 16 deletions

View File

@ -89,7 +89,8 @@ impl backend::Backend for Concrete {
// Is it a UTF-8 starting point? // Is it a UTF-8 starting point?
if 32 <= ch && ch <= 255 && ch != 127 { 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()) .unwrap())
} else { } else {
parse_ncurses_char(ch) parse_ncurses_char(ch)

View File

@ -78,6 +78,15 @@ impl EventResult {
EventResult::Ignored => false, 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 /// A non-character key on the keyboard

View File

@ -140,6 +140,10 @@ pub struct Cursive {
global_callbacks: HashMap<Event, Callback>, global_callbacks: HashMap<Event, Callback>,
menubar: views::Menubar, menubar: views::Menubar,
// Last layer sizes of the stack view.
// If it changed, clear the screen.
last_sizes: Vec<Vec2>,
active_screen: ScreenId, active_screen: ScreenId,
running: bool, running: bool,
@ -167,6 +171,7 @@ impl Cursive {
let mut res = Cursive { let mut res = Cursive {
theme: theme, theme: theme,
screens: Vec::new(), screens: Vec::new(),
last_sizes: Vec::new(),
global_callbacks: HashMap::new(), global_callbacks: HashMap::new(),
menubar: views::Menubar::new(), menubar: views::Menubar::new(),
active_screen: 0, active_screen: 0,
@ -436,6 +441,7 @@ impl Cursive {
/// Convenient method to remove a layer from the current screen. /// Convenient method to remove a layer from the current screen.
pub fn pop_layer(&mut self) { pub fn pop_layer(&mut self) {
self.screen_mut().pop_layer(); self.screen_mut().pop_layer();
self.clear();
} }
// Handles a key event when it was ignored by the current view // Handles a key event when it was ignored by the current view
@ -466,6 +472,13 @@ impl Cursive {
fn draw(&mut self) { fn draw(&mut self) {
// TODO: don't clone the theme // TODO: don't clone the theme
// Reference it or something // 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(), let printer = Printer::new(self.screen_size(),
self.theme.clone(), self.theme.clone(),
&self.backend); &self.backend);
@ -527,10 +540,7 @@ impl Cursive {
// * Current screen (top layer) // * Current screen (top layer)
// * Global callbacks // * Global callbacks
if self.menubar.receive_events() { if self.menubar.receive_events() {
if let EventResult::Consumed(Some(cb)) = self.menubar self.menubar.on_event(event).process(self);
.on_event(event) {
cb(self);
}
} else { } else {
match self.screen_mut().on_event(event) { match self.screen_mut().on_event(event) {
// If the event was ignored, // If the event was ignored,

View File

@ -100,7 +100,7 @@ fn show_child(s: &mut Cursive, offset: (usize, usize), menu: Rc<MenuTree>) {
s.pop_layer(); s.pop_layer();
s.select_menubar(); s.select_menubar();
// Act as if we sent "Right" then "Down" // 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() if let EventResult::Consumed(Some(cb)) = s.menubar()
.on_event(Event::Key(Key::Down)) { .on_event(Event::Key(Key::Down)) {
cb(s); cb(s);
@ -110,7 +110,7 @@ fn show_child(s: &mut Cursive, offset: (usize, usize), menu: Rc<MenuTree>) {
s.pop_layer(); s.pop_layer();
s.select_menubar(); s.select_menubar();
// Act as if we sent "Left" then "Down" // 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() if let EventResult::Consumed(Some(cb)) = s.menubar()
.on_event(Event::Key(Key::Down)) { .on_event(Event::Key(Key::Down)) {
cb(s); cb(s);

View File

@ -13,7 +13,6 @@ 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,7 +31,6 @@ impl StackView {
StackView { StackView {
layers: Vec::new(), layers: Vec::new(),
last_size: Vec2::zero(), last_size: Vec2::zero(),
needs_clear: false,
} }
} }
@ -58,7 +56,6 @@ 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();
self.needs_clear = true;
} }
/// Computes the offset of the current top view. /// Computes the offset of the current top view.
@ -71,13 +68,15 @@ impl StackView {
} }
previous previous
} }
/// Returns the size for each layer in this view.
pub fn layer_sizes(&self) -> Vec<Vec2> {
self.layers.iter().map(|layer| layer.size).collect()
}
} }
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| {
@ -110,9 +109,6 @@ impl View for StackView {
for layer in &mut self.layers { for layer in &mut self.layers {
// 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) {
self.needs_clear = true;
}
layer.size = size; layer.size = size;
layer.view.layout(layer.size); layer.view.layout(layer.size);