From 7652cc440dd64eccfd8463fae445c206b9cf65f7 Mon Sep 17 00:00:00 2001 From: Sebastian Woetzel Date: Mon, 8 May 2017 21:34:41 +0200 Subject: [PATCH] fixes panic when terminal was resized --- examples/barchart.rs | 15 +++++++++++---- examples/block.rs | 17 ++++++++++------ examples/canvas.rs | 45 ++++++++++++++++++++++++++++--------------- examples/chart.rs | 14 +++++++++++--- examples/gauge.rs | 15 +++++++++++---- examples/list.rs | 15 +++++++++++---- examples/paragraph.rs | 19 ++++++++++++------ examples/sparkline.rs | 15 +++++++++++---- examples/table.rs | 15 +++++++++++---- examples/tabs.rs | 17 +++++++++++----- 10 files changed, 132 insertions(+), 55 deletions(-) diff --git a/examples/barchart.rs b/examples/barchart.rs index cbaab4af..8088f79e 100644 --- a/examples/barchart.rs +++ b/examples/barchart.rs @@ -12,16 +12,18 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, BarChart}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color, Modifier}; struct App<'a> { + size: Rect, data: Vec<(&'a str, u64)>, } impl<'a> App<'a> { fn new() -> App<'a> { App { + size: Rect::default(), data: vec![("B1", 9), ("B2", 12), ("B3", 5), @@ -96,9 +98,16 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); loop { + let size = terminal.size().unwrap(); + if app.size != size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = rx.recv().unwrap(); match evt { Event::Input(input) => { @@ -118,13 +127,11 @@ fn main() { fn draw(t: &mut Terminal, app: &App) { - let size = t.size().unwrap(); - Group::default() .direction(Direction::Vertical) .margin(2) .sizes(&[Size::Percent(50), Size::Percent(50)]) - .render(t, &size, |t, chunks| { + .render(t, &app.size, |t, chunks| { BarChart::default() .block(Block::default().title("Data1").borders(border::ALL)) .data(&app.data) diff --git a/examples/block.rs b/examples/block.rs index c225ad9d..d869b5ba 100644 --- a/examples/block.rs +++ b/examples/block.rs @@ -8,7 +8,7 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color, Modifier}; fn main() { @@ -16,9 +16,16 @@ fn main() { let stdin = io::stdin(); terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); - draw(&mut terminal); + + let mut term_size = terminal.size().unwrap(); + draw(&mut terminal, &term_size); for c in stdin.keys() { - draw(&mut terminal); + let size = terminal.size().unwrap(); + if term_size != size { + terminal.resize(size).unwrap(); + term_size = size; + } + draw(&mut terminal, &term_size); let evt = c.unwrap(); if evt == event::Key::Char('q') { break; @@ -27,9 +34,7 @@ fn main() { terminal.show_cursor().unwrap(); } -fn draw(t: &mut Terminal) { - - let size = t.size().unwrap(); +fn draw(t: &mut Terminal, size: &Rect) { // Wrapping block for a group // Just draw the block and the group on the same area and build the group diff --git a/examples/canvas.rs b/examples/canvas.rs index 5ceb7bc0..2632342b 100644 --- a/examples/canvas.rs +++ b/examples/canvas.rs @@ -24,6 +24,8 @@ struct App { playground: Rect, vx: u16, vy: u16, + dir_x: bool, + dir_y: bool, } @@ -33,23 +35,36 @@ impl App { size: Default::default(), x: 0.0, y: 0.0, - ball: Rect::new(20, 20, 10, 10), + ball: Rect::new(10, 30, 10, 10), playground: Rect::new(10, 10, 100, 100), vx: 1, vy: 1, + dir_x: true, + dir_y: true, } } fn advance(&mut self) { if self.ball.left() < self.playground.left() || - self.ball.right() > self.playground.right() { - self.vx = !self.vx; - } else if self.ball.top() < self.playground.top() || - self.ball.bottom() > self.playground.bottom() { - self.vy = !self.vy; + self.ball.right() > self.playground.right() { + self.dir_x = !self.dir_x; + } + if self.ball.top() < self.playground.top() || + self.ball.bottom() > self.playground.bottom() { + self.dir_y = !self.dir_y; + } + + if self.dir_x { + self.ball.x += self.vx; + } else { + self.ball.x -= self.vx; + } + + if self.dir_y { + self.ball.y += self.vy; + } else { + self.ball.y -= self.vy } - self.ball.x += self.vx; - self.ball.y += self.vy; } } @@ -94,11 +109,16 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); - let size = terminal.size().unwrap(); - app.size = size; + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); loop { + let size = terminal.size().unwrap(); + if size != app.size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = rx.recv().unwrap(); match evt { Event::Input(input) => { @@ -126,11 +146,6 @@ fn main() { app.advance(); } } - let size = terminal.size().unwrap(); - if size != app.size { - app.size = size; - terminal.resize(size).unwrap(); - } draw(&mut terminal, &app); } diff --git a/examples/chart.rs b/examples/chart.rs index 08c4b5a8..1481eab6 100644 --- a/examples/chart.rs +++ b/examples/chart.rs @@ -15,9 +15,11 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, Chart, Axis, Marker, Dataset}; +use tui::layout::Rect; use tui::style::{Style, Color, Modifier}; struct App { + size: Rect, signal1: SinSignal, data1: Vec<(f64, f64)>, signal2: SinSignal, @@ -32,6 +34,7 @@ impl App { let data1 = signal1.by_ref().take(200).collect::>(); let data2 = signal2.by_ref().take(200).collect::>(); App { + size: Rect::default(), signal1: signal1, data1: data1, signal2: signal2, @@ -95,9 +98,16 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); loop { + let size = terminal.size().unwrap(); + if app.size != size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = rx.recv().unwrap(); match evt { Event::Input(input) => { @@ -117,8 +127,6 @@ fn main() { fn draw(t: &mut Terminal, app: &App) { - let size = t.size().unwrap(); - Chart::default() .block(Block::default() .title("Chart") @@ -150,7 +158,7 @@ fn draw(t: &mut Terminal, app: &App) { .marker(Marker::Braille) .style(Style::default().fg(Color::Yellow)) .data(&app.data2)]) - .render(t, &size); + .render(t, &app.size); t.draw().unwrap(); } diff --git a/examples/gauge.rs b/examples/gauge.rs index 846ae5a1..74ddf4c0 100644 --- a/examples/gauge.rs +++ b/examples/gauge.rs @@ -12,10 +12,11 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, Gauge}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color, Modifier}; struct App { + size: Rect, progress1: u16, progress2: u16, progress3: u16, @@ -25,6 +26,7 @@ struct App { impl App { fn new() -> App { App { + size: Rect::default(), progress1: 0, progress2: 0, progress3: 0, @@ -93,9 +95,16 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); loop { + let size = terminal.size().unwrap(); + if size != app.size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = rx.recv().unwrap(); match evt { Event::Input(input) => { @@ -115,13 +124,11 @@ fn main() { fn draw(t: &mut Terminal, app: &App) { - let size = t.size().unwrap(); - Group::default() .direction(Direction::Vertical) .margin(2) .sizes(&[Size::Percent(25), Size::Percent(25), Size::Percent(25), Size::Percent(25)]) - .render(t, &size, |t, chunks| { + .render(t, &app.size, |t, chunks| { Gauge::default() .block(Block::default().title("Gauge1").borders(border::ALL)) .style(Style::default().fg(Color::Yellow)) diff --git a/examples/list.rs b/examples/list.rs index 705a1dac..86baff06 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -12,10 +12,11 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, SelectableList, List}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color, Modifier}; struct App<'a> { + size: Rect, items: Vec<&'a str>, selected: usize, events: Vec<(&'a str, &'a str)>, @@ -28,6 +29,7 @@ struct App<'a> { impl<'a> App<'a> { fn new() -> App<'a> { App { + size: Rect::default(), items: vec!["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9", "Item10", "Item11", "Item12", "Item13", "Item14", "Item15", "Item16", "Item17", "Item18", "Item19", "Item20", "Item21", "Item22", @@ -113,9 +115,16 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); loop { + let size = terminal.size().unwrap(); + if size != app.size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = rx.recv().unwrap(); match evt { Event::Input(input) => { @@ -151,12 +160,10 @@ fn main() { fn draw(t: &mut Terminal, app: &App) { - let size = t.size().unwrap(); - Group::default() .direction(Direction::Horizontal) .sizes(&[Size::Percent(50), Size::Percent(50)]) - .render(t, &size, |t, chunks| { + .render(t, &app.size, |t, chunks| { SelectableList::default() .block(Block::default() .borders(border::ALL) diff --git a/examples/paragraph.rs b/examples/paragraph.rs index f8dac576..521b101a 100644 --- a/examples/paragraph.rs +++ b/examples/paragraph.rs @@ -8,7 +8,7 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, Paragraph}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color}; fn main() { @@ -16,9 +16,18 @@ fn main() { let stdin = io::stdin(); terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); - draw(&mut terminal); + + let mut term_size = terminal.size().unwrap(); + draw(&mut terminal, &term_size); + for c in stdin.keys() { - draw(&mut terminal); + let size = terminal.size().unwrap(); + if size != term_size { + terminal.resize(size).unwrap(); + term_size = size; + } + + draw(&mut terminal, &term_size); let evt = c.unwrap(); if evt == event::Key::Char('q') { break; @@ -27,9 +36,7 @@ fn main() { terminal.show_cursor().unwrap(); } -fn draw(t: &mut Terminal) { - - let size = t.size().unwrap(); +fn draw(t: &mut Terminal, size: &Rect) { Block::default() .style(Style::default().bg(Color::White)) diff --git a/examples/sparkline.rs b/examples/sparkline.rs index d737f89c..05a831c1 100644 --- a/examples/sparkline.rs +++ b/examples/sparkline.rs @@ -15,10 +15,11 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, Sparkline}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color}; struct App { + size: Rect, signal: RandomSignal, data1: Vec, data2: Vec, @@ -32,6 +33,7 @@ impl App { let data2 = signal.by_ref().take(200).collect::>(); let data3 = signal.by_ref().take(200).collect::>(); App { + size: Rect::default(), signal: signal, data1: data1, data2: data2, @@ -93,9 +95,16 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); loop { + let size = terminal.size().unwrap(); + if size != app.size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = rx.recv().unwrap(); match evt { Event::Input(input) => { @@ -115,13 +124,11 @@ fn main() { fn draw(t: &mut Terminal, app: &App) { - let size = t.size().unwrap(); - Group::default() .direction(Direction::Vertical) .margin(2) .sizes(&[Size::Fixed(3), Size::Fixed(3), Size::Fixed(7), Size::Min(0)]) - .render(t, &size, |t, chunks| { + .render(t, &app.size, |t, chunks| { Sparkline::default() .block(Block::default().title("Data1").borders(border::LEFT | border::RIGHT)) .data(&app.data1) diff --git a/examples/table.rs b/examples/table.rs index 27b433f0..553a29be 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -9,10 +9,11 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, Table}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color, Modifier}; struct App<'a> { + size: Rect, items: Vec>, selected: usize, } @@ -20,6 +21,7 @@ struct App<'a> { impl<'a> App<'a> { fn new() -> App<'a> { App { + size: Rect::default(), items: vec![vec!["Row12", "Row12", "Row13"], vec!["Row21", "Row22", "Row23"], vec!["Row31", "Row32", "Row33"], @@ -43,11 +45,18 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &app); // Input let stdin = io::stdin(); for c in stdin.keys() { + let size = terminal.size().unwrap(); + if size != app.size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = c.unwrap(); match evt { event::Key::Char('q') => { @@ -76,13 +85,11 @@ fn main() { fn draw(t: &mut Terminal, app: &App) { - let size = t.size().unwrap(); - Group::default() .direction(Direction::Horizontal) .sizes(&[Size::Percent(100)]) .margin(5) - .render(t, &size, |t, chunks| { + .render(t, &app.size, |t, chunks| { let selected_style = Style::default().fg(Color::Yellow).modifier(Modifier::Bold); let normal_style = Style::default().fg(Color::White); Table::default() diff --git a/examples/tabs.rs b/examples/tabs.rs index c713c75d..62abe059 100644 --- a/examples/tabs.rs +++ b/examples/tabs.rs @@ -11,10 +11,11 @@ use termion::input::TermRead; use tui::Terminal; use tui::backend::TermionBackend; use tui::widgets::{Widget, Block, border, Tabs}; -use tui::layout::{Group, Direction, Size}; +use tui::layout::{Group, Direction, Size, Rect}; use tui::style::{Style, Color}; struct App<'a> { + size: Rect, tabs: MyTabs<'a>, } @@ -25,6 +26,7 @@ fn main() { // App let mut app = App { + size: Rect::default(), tabs: MyTabs { titles: vec!["Tab0", "Tab1", "Tab2", "Tab3"], selection: 0, @@ -34,11 +36,18 @@ fn main() { // First draw call terminal.clear().unwrap(); terminal.hide_cursor().unwrap(); + app.size = terminal.size().unwrap(); draw(&mut terminal, &mut app); // Main loop let stdin = io::stdin(); for c in stdin.keys() { + let size = terminal.size().unwrap(); + if size != app.size { + terminal.resize(size).unwrap(); + app.size = size; + } + let evt = c.unwrap(); match evt { event::Key::Char('q') => { @@ -56,17 +65,15 @@ fn main() { fn draw(t: &mut Terminal, app: &mut App) { - let size = t.size().unwrap(); - Block::default() .style(Style::default().bg(Color::White)) - .render(t, &size); + .render(t, &app.size); Group::default() .direction(Direction::Vertical) .margin(5) .sizes(&[Size::Fixed(3), Size::Min(0)]) - .render(t, &size, |t, chunks| { + .render(t, &app.size, |t, chunks| { Tabs::default() .block(Block::default().borders(border::ALL).title("Tabs")) .titles(&app.tabs.titles)