Cleaner scroll handling

This commit is contained in:
2026-07-31 15:15:55 +02:00
parent 0f7d25627d
commit d779ac1a59
2 changed files with 58 additions and 43 deletions
+48 -31
View File
@@ -15,58 +15,75 @@ pub struct RenderScope {
draw_instructions: Vec<Instr>,
}
struct RenderTextResult {
text: String,
line_len: u16,
lines_len: u16,
}
impl RenderTextResult {
fn insert_newline(&mut self, height: u16) -> bool {
if self.lines_len >= height {
return true;
}
self.text.push('\n');
self.line_len = 0;
self.lines_len += 1;
false
}
fn insert(&mut self, c: char) {
self.text.push(c);
self.line_len += 1;
}
}
impl RenderScope {
pub fn draw_text<P: Into<Point>, T: Display>(&mut self, at: P, text: T) -> u16 {
let point: Point = at.into();
let lines = text
.to_string()
.lines()
.map(|line| {
let mut chars = line.chars().peekable();
let mut new_line = String::new();
let mut len = 0;
let text = text.to_string();
let mut chars = text.chars().peekable();
let mut result = RenderTextResult {
text: String::new(),
line_len: 0,
lines_len: 1,
};
while let Some(c) = chars.next() {
if c == '\x1b' && chars.peek() == Some(&'[') {
new_line.push(c);
result.text.push(c);
while let Some(c) = chars.next() {
new_line.push(c);
result.text.push(c);
if c.is_ascii_alphabetic() {
break;
}
}
continue;
} else if c == '\n' {
if result.insert_newline(self.rect.height) {
break;
}
} else {
result.insert(c);
new_line.push(c);
len += 1;
if len >= self.rect.width as usize {
new_line.push('\n');
len = 0;
if result.line_len >= self.rect.width {
if result.insert_newline(self.rect.height) {
break;
}
}
}
}
new_line
})
.collect::<Vec<_>>()
.join("\n");
let lines = lines
.lines()
.take((self.rect.height - point.y) as usize)
.collect::<Vec<_>>();
let lines_len = lines.len();
self.draw_instructions
.push(Instr::DrawText(point, lines.join("\n")));
.push(Instr::DrawText(point, result.text));
lines_len as u16
result.lines_len
}
}
+2 -4
View File
@@ -10,9 +10,7 @@ pub struct ScrollText {
impl Widget for ScrollText {
fn render(&self, scope: &mut crate::render::RenderScope) {
scope.draw_text(0, &self.title);
let title_lines = self.title.lines().count();
let title_lines = scope.draw_text(0, &self.title);
let mut y = title_lines as u16;
@@ -20,7 +18,7 @@ impl Widget for ScrollText {
.text
.lines()
.skip(self.scroll)
.take(scope.rect.height as usize - title_lines)
.take((scope.rect.height - title_lines) as usize)
{
y += scope.draw_text((0, y), line);
}