Doing screen buffering to eliminate flicker.

At the moment, it's brain-dead and really slow.
This commit is contained in:
Nathan Vegdahl 2017-12-31 18:51:02 -08:00
parent b63bb6f87d
commit 66a80baeed
2 changed files with 76 additions and 15 deletions

View File

@ -52,6 +52,7 @@ macro_rules! ui_loop {
$term_ui.width = w as usize; $term_ui.width = w as usize;
$term_ui.height = h as usize; $term_ui.height = h as usize;
$term_ui.editor.update_dim($term_ui.height - 1, $term_ui.width); $term_ui.editor.update_dim($term_ui.height - 1, $term_ui.width);
$term_ui.screen.resize(w as usize, h as usize);
} }
if stop || $term_ui.quit { if stop || $term_ui.quit {

View File

@ -1,7 +1,10 @@
use std;
use std::cell::RefCell; use std::cell::RefCell;
use std::io; use std::io;
use std::io::Write; use std::io::Write;
use unicode_width::UnicodeWidthStr;
use unicode_segmentation::UnicodeSegmentation;
use termion; use termion;
use termion::screen::AlternateScreen; use termion::screen::AlternateScreen;
use termion::color; use termion::color;
@ -9,29 +12,81 @@ use termion::raw::{IntoRawMode, RawTerminal};
pub(crate) struct Screen { pub(crate) struct Screen {
out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>, out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>,
buf: RefCell<Vec<Option<String>>>,
w: usize,
h: usize,
} }
impl Screen { impl Screen {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let (w, h) = termion::terminal_size().unwrap();
let buf = std::iter::repeat(Some(format!(
"{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
))).take(w as usize * h as usize)
.collect();
Screen { Screen {
out: RefCell::new(AlternateScreen::from(io::stdout().into_raw_mode().unwrap())), out: RefCell::new(AlternateScreen::from(io::stdout().into_raw_mode().unwrap())),
buf: RefCell::new(buf),
w: w as usize,
h: h as usize,
} }
} }
pub(crate) fn clear(&self) { pub(crate) fn clear(&self) {
write!( for cell in self.buf.borrow_mut().iter_mut() {
self.out.borrow_mut(), match *cell {
"{}{}", Some(ref mut text) => {
color::Bg(color::Black), text.clear();
termion::clear::All text.push_str(&format!(
).unwrap(); "{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
));
}
_ => {
*cell = Some(format!(
"{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
));
}
}
}
}
pub(crate) fn resize(&mut self, w: usize, h: usize) {
self.w = w;
self.h = h;
self.buf.borrow_mut().resize(
w * h,
Some(format!(
"{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
)),
);
} }
pub(crate) fn present(&self) { pub(crate) fn present(&self) {
let buf = self.buf.borrow();
for y in 0..self.h {
for x in 0..self.w {
if let Some(ref cell) = buf[y * self.w + x] {
write!(
self.out.borrow_mut(),
"{}{}",
termion::cursor::Goto((x + 1) as u16, (y + 1) as u16),
cell
).unwrap();
}
}
}
self.out.borrow_mut().flush().unwrap(); self.out.borrow_mut().flush().unwrap();
} }
pub(crate) fn draw<C1: color::Color, C2: color::Color>( pub(crate) fn draw<C1: color::Color + Copy, C2: color::Color + Copy>(
&self, &self,
x: usize, x: usize,
y: usize, y: usize,
@ -39,14 +94,19 @@ impl Screen {
fg: C1, fg: C1,
bg: C2, bg: C2,
) { ) {
write!( let mut buf = self.buf.borrow_mut();
self.out.borrow_mut(), let mut x = x;
"{}{}{}{}", for g in UnicodeSegmentation::graphemes(text, true) {
termion::cursor::Goto((x + 1) as u16, (y + 1) as u16), let width = UnicodeWidthStr::width(g);
color::Fg(fg), if width > 0 {
color::Bg(bg), buf[y * self.w + x] = Some(format!("{}{}{}", color::Fg(fg), color::Bg(bg), g));
text x += 1;
).unwrap(); for _ in 0..(width - 1) {
buf[y * self.w + x] = None;
x += 1;
}
}
}
} }
pub(crate) fn hide_cursor(&self) { pub(crate) fn hide_cursor(&self) {