ui: draw to terminal with horizontal sweeping
sweep each line in the dirty areas and avoid redraws because of area overlapembed
parent
cb83f9fe05
commit
e0df6ce22d
120
ui/src/state.rs
120
ui/src/state.rs
|
@ -368,69 +368,95 @@ impl State {
|
||||||
for i in 0..self.components.len() {
|
for i in 0..self.components.len() {
|
||||||
self.draw_component(i);
|
self.draw_component(i);
|
||||||
}
|
}
|
||||||
let areas: Vec<Area> = self.context.dirty_areas.drain(0..).collect();
|
let mut areas: Vec<Area> = self.context.dirty_areas.drain(0..).collect();
|
||||||
|
/* Sort by x_start, ie upper_left corner's x coordinate */
|
||||||
|
areas.sort_by(|a, b| (a.0).0.partial_cmp(&(b.0).0).unwrap());
|
||||||
/* draw each dirty area */
|
/* draw each dirty area */
|
||||||
for a in areas {
|
let cols = self.cols;
|
||||||
self.draw_area(a);
|
let rows = self.rows;
|
||||||
}
|
for y in 0..rows {
|
||||||
}
|
let mut segment = None;
|
||||||
|
for ((x_start, y_start), (x_end, y_end)) in &areas {
|
||||||
/// Draw only a specific `area` on the screen.
|
if y < *y_start || y > *y_end {
|
||||||
fn draw_area(&mut self, area: Area) {
|
continue;
|
||||||
let upper_left = upper_left!(area);
|
|
||||||
let bottom_right = bottom_right!(area);
|
|
||||||
|
|
||||||
for y in get_y(upper_left)..=get_y(bottom_right) {
|
|
||||||
write!(
|
|
||||||
self.stdout(),
|
|
||||||
"{}",
|
|
||||||
cursor::Goto(get_x(upper_left) as u16 + 1, (y + 1) as u16)
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
for x in get_x(upper_left)..=get_x(bottom_right) {
|
|
||||||
let c = self.grid[(x, y)];
|
|
||||||
|
|
||||||
if c.bg() != Color::Default {
|
|
||||||
write!(self.stdout(), "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
|
|
||||||
}
|
}
|
||||||
if c.fg() != Color::Default {
|
if let Some((x_start, x_end)) = segment.take() {
|
||||||
write!(self.stdout(), "{}", termion::color::Fg(c.fg().as_termion())).unwrap();
|
self.draw_horizontal_segment(x_start, x_end, y);
|
||||||
}
|
}
|
||||||
write!(self.stdout(), "{}", c.ch()).unwrap();
|
match segment {
|
||||||
if c.bg() != Color::Default {
|
ref mut s @ None => {
|
||||||
write!(
|
*s = Some((*x_start, *x_end));
|
||||||
self.stdout(),
|
}
|
||||||
"{}",
|
ref mut s @ Some(_) if s.unwrap().1 < *x_start => {
|
||||||
termion::color::Bg(termion::color::Reset)
|
self.draw_horizontal_segment(s.unwrap().0, s.unwrap().1, y);
|
||||||
)
|
*s = Some((*x_start, *x_end));
|
||||||
.unwrap();
|
}
|
||||||
}
|
ref mut s @ Some(_) if s.unwrap().1 < *x_end => {
|
||||||
if c.fg() != Color::Default {
|
self.draw_horizontal_segment(s.unwrap().0, s.unwrap().1, y);
|
||||||
write!(
|
*s = Some((s.unwrap().1, *x_end));
|
||||||
self.stdout(),
|
}
|
||||||
"{}",
|
Some((_, ref mut x)) => {
|
||||||
termion::color::Fg(termion::color::Reset)
|
*x = *x_end;
|
||||||
)
|
}
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some((x_start, x_end)) = segment {
|
||||||
|
self.draw_horizontal_segment(x_start, x_end, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.flush();
|
self.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw only a specific `area` on the screen.
|
||||||
|
fn draw_horizontal_segment(&mut self, x_start: usize, x_end: usize, y: usize) {
|
||||||
|
write!(
|
||||||
|
self.stdout(),
|
||||||
|
"{}",
|
||||||
|
cursor::Goto(x_start as u16 + 1, (y + 1) as u16)
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
for x in x_start..=x_end {
|
||||||
|
let c = self.grid[(x, y)];
|
||||||
|
|
||||||
|
if c.bg() != Color::Default {
|
||||||
|
write!(self.stdout(), "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
|
||||||
|
}
|
||||||
|
if c.fg() != Color::Default {
|
||||||
|
write!(self.stdout(), "{}", termion::color::Fg(c.fg().as_termion())).unwrap();
|
||||||
|
}
|
||||||
|
write!(self.stdout(), "{}", c.ch()).unwrap();
|
||||||
|
let mut b = [0; 4];
|
||||||
|
if c.bg() != Color::Default {
|
||||||
|
write!(
|
||||||
|
self.stdout(),
|
||||||
|
"{}",
|
||||||
|
termion::color::Bg(termion::color::Reset)
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
if c.fg() != Color::Default {
|
||||||
|
write!(
|
||||||
|
self.stdout(),
|
||||||
|
"{}",
|
||||||
|
termion::color::Fg(termion::color::Reset)
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Draw the entire screen from scratch.
|
/// Draw the entire screen from scratch.
|
||||||
pub fn render(&mut self) {
|
pub fn render(&mut self) {
|
||||||
self.update_size();
|
self.update_size();
|
||||||
|
|
||||||
/* draw each component */
|
|
||||||
for i in 0..self.components.len() {
|
|
||||||
self.draw_component(i);
|
|
||||||
}
|
|
||||||
let cols = self.cols;
|
let cols = self.cols;
|
||||||
let rows = self.rows;
|
let rows = self.rows;
|
||||||
|
self.context
|
||||||
|
.dirty_areas
|
||||||
|
.push_back(((0, 0), (cols - 1, rows - 1)));
|
||||||
|
|
||||||
self.draw_area(((0, 0), (cols - 1, rows - 1)));
|
self.redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_component(&mut self, idx: usize) {
|
pub fn draw_component(&mut self, idx: usize) {
|
||||||
let component = &mut self.components[idx];
|
let component = &mut self.components[idx];
|
||||||
let upper_left = (0, 0);
|
let upper_left = (0, 0);
|
||||||
|
|
Loading…
Reference in New Issue