Fix text alignment when wrapped (#471)

* Fix text alignment when wrapped

This changes the `LinesIterator` to return a `width` that corresponds
with the actual total length of the chunks, rather than returning the
total available width, when a line is wrapped. This effectively reverts
20cb033b8d (I am not sure why that commit
changed it).

* Add `is_wrapped` flag to `Row`

* Fix TextArea width with wrapped rows

Co-authored-by: Alexandre Bury <alexandre.bury@gmail.com>
This commit is contained in:
James Tai 2020-07-25 16:51:33 -07:00 committed by GitHub
parent d96904a07d
commit bc49eebeb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 18 deletions

View File

@ -67,8 +67,15 @@ impl<'a> Iterator for LinesIterator<'a> {
let start = row.segments.first()?.start; let start = row.segments.first()?.start;
let end = row.segments.last()?.end; let end = row.segments.last()?.end;
let width = row.width; let spans::Row {
width, is_wrapped, ..
} = row;
Some(Row { start, end, width }) Some(Row {
start,
end,
width,
is_wrapped,
})
} }
} }

View File

@ -10,8 +10,12 @@ pub struct Row {
pub start: usize, pub start: usize,
/// End of the row (excluded) /// End of the row (excluded)
pub end: usize, pub end: usize,
/// Width of the row, in cells. /// Width of the row, in cells.
pub width: usize, pub width: usize,
/// Whether or not this text was wrapped onto the next line
pub is_wrapped: bool,
} }
impl Row { impl Row {

View File

@ -149,16 +149,10 @@ where
// We can know text was wrapped if the stop was optional, // We can know text was wrapped if the stop was optional,
// and there's more coming. // and there's more coming.
let text_wrap = !chunks.last().map(|c| c.hard_stop).unwrap_or(true) let is_wrapped = !chunks.last().map(|c| c.hard_stop).unwrap_or(true)
&& self.iter.peek().is_some(); && self.iter.peek().is_some();
// If we had to break a line in two, then at least pretent we're let width = chunks.iter().map(|c| c.width).sum();
// taking the full width.
let width = if text_wrap {
self.width
} else {
chunks.iter().map(|c| c.width).sum()
};
assert!(width <= self.width); assert!(width <= self.width);
@ -170,6 +164,10 @@ where
// TODO: merge consecutive segments of the same span // TODO: merge consecutive segments of the same span
Some(Row { segments, width }) Some(Row {
segments,
width,
is_wrapped,
})
} }
} }

View File

@ -8,6 +8,8 @@ pub struct Row {
pub segments: Vec<Segment>, pub segments: Vec<Segment>,
/// Total width for this row /// Total width for this row
pub width: usize, pub width: usize,
/// Whether or not this text was wrapped onto the next line
pub is_wrapped: bool,
} }
impl Row { impl Row {

View File

@ -287,6 +287,7 @@ impl TextArea {
start: self.content.len(), start: self.content.len(),
end: self.content.len(), end: self.content.len(),
width: 0, width: 0,
is_wrapped: false,
}); });
} }
} }
@ -471,12 +472,15 @@ impl View for TextArea {
// And y = number of rows // And y = number of rows
debug!("{:?}", self.rows); debug!("{:?}", self.rows);
let scroll_width = if self.rows.len() > constraint.y { 1 } else { 0 }; let scroll_width = if self.rows.len() > constraint.y { 1 } else { 0 };
Vec2::new(
scroll_width let content_width = if self.rows.iter().any(|row| row.is_wrapped) {
+ 1 // If any row has been wrapped, we want to take the full width.
+ self.rows.iter().map(|r| r.width).max().unwrap_or(1), constraint.x.saturating_sub(1 + scroll_width)
self.rows.len(), } else {
) self.rows.iter().map(|r| r.width).max().unwrap_or(1)
};
Vec2::new(scroll_width + 1 + content_width, self.rows.len())
} }
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {

View File

@ -357,7 +357,12 @@ impl TextView {
LinesIterator::new(content.get_cache().as_ref(), size.x).collect(); LinesIterator::new(content.get_cache().as_ref(), size.x).collect();
// Desired width // Desired width
self.width = self.rows.iter().map(|row| row.width).max(); self.width = if self.rows.iter().any(|row| row.is_wrapped) {
// If any rows are wrapped, then require the full width.
Some(size.x)
} else {
self.rows.iter().map(|row| row.width).max()
}
} }
} }