Move buffer copy to its own function, it's more readable

This commit is contained in:
2023-11-05 08:23:31 +01:00
parent 1199dd7613
commit b81ec4ae4f

View File

@ -124,20 +124,24 @@ impl Component for Backlog {
value: PrerenderValue::Rendered(buf), value: PrerenderValue::Rendered(buf),
}) if *key == text_area.width => { }) if *key == text_area.width => {
// We already rendered it, copy the buffer. // We already rendered it, copy the buffer.
assert_eq!(buf.area().width, text_area.width); assert_eq!(text_area.width, buf.area.width);
for (y, line) in buf let top_padding = text_area.height.saturating_sub(buf.area.height);
.content() let skip_top_lines = buf.area.height.saturating_sub(text_area.height);
.chunks(u16::min(buf.area().width, text_area.width) as usize) copy_buffer(
.enumerate() buf,
.skip(buf.area().height.saturating_sub(text_area.height) as usize) Rect {
{ x: 0,
for (x, cell) in line.into_iter().enumerate() { y: 0,
*frame.buffer_mut().get_mut( width: text_area.width,
text_area.x + (x as u16), height: buf.area.height - skip_top_lines,
text_area.y + text_area.height + (y as u16) - buf.area().height, },
) = cell.clone(); frame.buffer_mut(),
} Rect {
} y: text_area.y + top_padding,
height: text_area.height - top_padding,
..text_area
},
);
buf.area().height buf.area().height
}, },
@ -145,28 +149,37 @@ impl Component for Backlog {
let widget = BottomAlignedParagraph::new(item.text); let widget = BottomAlignedParagraph::new(item.text);
let height = widget.render_overlap(text_area, frame.buffer_mut()); let height = widget.render_overlap(text_area, frame.buffer_mut());
// Copy the drawn result to a buffer for caching // If the whole widget fits in the text_area, copy the drawn result to a buffer
let mut buf = ratatui::buffer::Buffer::empty(Rect { // for caching
x: 0, if height <= text_area.height {
y: 0, let mut buf = ratatui::buffer::Buffer::empty(Rect {
width: text_area.width, x: 0,
height, y: 0,
}); width: text_area.width,
for y in 0..height { height,
// TODO: only copy the width actually drawn by the widget });
for x in 0..text_area.width { let top_padding = text_area.height.saturating_sub(buf.area.height);
*buf.get_mut(x, y) = frame copy_buffer(
.buffer_mut() frame.buffer_mut(),
.get(text_area.x + x, text_area.y + text_area.height + y - height) Rect {
.clone() y: text_area.y + top_padding,
} height: text_area.height - top_padding,
..text_area
},
&mut buf,
Rect {
x: 0,
y: 0,
width: text_area.width, // TODO: only copy the width actually drawn by the widget
height: height,
},
);
*prerender = Some(PrerenderInner {
key: text_area.width,
value: PrerenderValue::Rendered(buf),
});
} }
*prerender = Some(PrerenderInner {
key: text_area.width,
value: PrerenderValue::Rendered(buf),
});
height height
}, },
}; };
@ -185,3 +198,44 @@ impl Component for Backlog {
Ok(()) Ok(())
} }
} }
fn copy_buffer(src: &Buffer, src_area: Rect, dst: &mut Buffer, dst_area: Rect) {
assert_eq!(src_area.width, dst_area.width, "width mismatch");
assert_eq!(src_area.height, dst_area.height, "height mismatch");
assert!(
src_area.x + src_area.width <= src.area.width,
"src width overflow"
);
assert!(
src_area.y + src_area.height <= src.area.height,
"src height overflow"
);
assert!(
dst_area.x + dst_area.width <= dst.area.width,
"dst width overflow"
);
assert!(
dst_area.y + dst_area.height <= dst.area.height,
"dst height overflow"
);
for (y, line) in src
.content()
.chunks(src.area.width as usize)
.skip(src_area.y as usize)
.take(dst_area.height as usize)
.enumerate()
{
for (x, cell) in line
.into_iter()
.skip(src_area.x as usize)
.take(src_area.width as usize)
.enumerate()
{
*dst.get_mut(dst_area.x + (x as u16), dst_area.y + (y as u16)) = src
.get(src_area.x + (x as u16), src_area.y + (y as u16))
.clone();
}
}
}