Cleaner scroll handling
This commit is contained in:
+56
-39
@@ -15,58 +15,75 @@ pub struct RenderScope {
|
|||||||
draw_instructions: Vec<Instr>,
|
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 {
|
impl RenderScope {
|
||||||
pub fn draw_text<P: Into<Point>, T: Display>(&mut self, at: P, text: T) -> u16 {
|
pub fn draw_text<P: Into<Point>, T: Display>(&mut self, at: P, text: T) -> u16 {
|
||||||
let point: Point = at.into();
|
let point: Point = at.into();
|
||||||
|
|
||||||
let lines = text
|
let text = text.to_string();
|
||||||
.to_string()
|
|
||||||
.lines()
|
let mut chars = text.chars().peekable();
|
||||||
.map(|line| {
|
|
||||||
let mut chars = line.chars().peekable();
|
let mut result = RenderTextResult {
|
||||||
let mut new_line = String::new();
|
text: String::new(),
|
||||||
let mut len = 0;
|
line_len: 0,
|
||||||
|
lines_len: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(c) = chars.next() {
|
||||||
|
if c == '\x1b' && chars.peek() == Some(&'[') {
|
||||||
|
result.text.push(c);
|
||||||
|
|
||||||
while let Some(c) = chars.next() {
|
while let Some(c) = chars.next() {
|
||||||
if c == '\x1b' && chars.peek() == Some(&'[') {
|
result.text.push(c);
|
||||||
new_line.push(c);
|
|
||||||
|
|
||||||
while let Some(c) = chars.next() {
|
if c.is_ascii_alphabetic() {
|
||||||
new_line.push(c);
|
break;
|
||||||
|
|
||||||
if c.is_ascii_alphabetic() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_line.push(c);
|
|
||||||
len += 1;
|
|
||||||
|
|
||||||
if len >= self.rect.width as usize {
|
|
||||||
new_line.push('\n');
|
|
||||||
len = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if c == '\n' {
|
||||||
|
if result.insert_newline(self.rect.height) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.insert(c);
|
||||||
|
|
||||||
new_line
|
if result.line_len >= self.rect.width {
|
||||||
})
|
if result.insert_newline(self.rect.height) {
|
||||||
.collect::<Vec<_>>()
|
break;
|
||||||
.join("\n");
|
}
|
||||||
|
}
|
||||||
let lines = lines
|
}
|
||||||
.lines()
|
}
|
||||||
.take((self.rect.height - point.y) as usize)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let lines_len = lines.len();
|
|
||||||
|
|
||||||
self.draw_instructions
|
self.draw_instructions
|
||||||
.push(Instr::DrawText(point, lines.join("\n")));
|
.push(Instr::DrawText(point, result.text));
|
||||||
|
|
||||||
lines_len as u16
|
result.lines_len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ pub struct ScrollText {
|
|||||||
|
|
||||||
impl Widget for ScrollText {
|
impl Widget for ScrollText {
|
||||||
fn render(&self, scope: &mut crate::render::RenderScope) {
|
fn render(&self, scope: &mut crate::render::RenderScope) {
|
||||||
scope.draw_text(0, &self.title);
|
let title_lines = scope.draw_text(0, &self.title);
|
||||||
|
|
||||||
let title_lines = self.title.lines().count();
|
|
||||||
|
|
||||||
let mut y = title_lines as u16;
|
let mut y = title_lines as u16;
|
||||||
|
|
||||||
@@ -20,7 +18,7 @@ impl Widget for ScrollText {
|
|||||||
.text
|
.text
|
||||||
.lines()
|
.lines()
|
||||||
.skip(self.scroll)
|
.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);
|
y += scope.draw_text((0, y), line);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user