mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
fix: consider scrollable in TextArea required size
This commit is contained in:
parent
94c67b2257
commit
20e6938bbb
@ -156,9 +156,12 @@ impl<T: View> ViewWrapper for BoxView<T> {
|
|||||||
|
|
||||||
let req = self.size.zip_map(req, SizeConstraint::available);
|
let req = self.size.zip_map(req, SizeConstraint::available);
|
||||||
let child_size = self.view.required_size(req);
|
let child_size = self.view.required_size(req);
|
||||||
|
|
||||||
let result = self.size
|
let result = self.size
|
||||||
.zip_map(child_size.zip(req), SizeConstraint::result);
|
.zip_map(child_size.zip(req), SizeConstraint::result);
|
||||||
|
|
||||||
|
// println_stderr!("{:?}", result);
|
||||||
|
|
||||||
if self.squishable {
|
if self.squishable {
|
||||||
// We respect the request if we're less or equal.
|
// We respect the request if we're less or equal.
|
||||||
let respect_req = result.zip_map(req, |res, req| res <= req);
|
let respect_req = result.zip_map(req, |res, req| res <= req);
|
||||||
|
@ -36,9 +36,7 @@ pub struct TextArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_rows(text: &str, width: usize) -> Vec<Row> {
|
fn make_rows(text: &str, width: usize) -> Vec<Row> {
|
||||||
LinesIterator::new(text, width)
|
LinesIterator::new(text, width).show_spaces().collect()
|
||||||
.show_spaces()
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_default!(TextArea);
|
new_default!(TextArea);
|
||||||
@ -157,10 +155,7 @@ impl TextArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let text = &self.content[self.rows[row].start..self.cursor];
|
let text = &self.content[self.rows[row].start..self.cursor];
|
||||||
text.graphemes(true)
|
text.graphemes(true).last().unwrap().len()
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.len()
|
|
||||||
};
|
};
|
||||||
self.cursor -= len;
|
self.cursor -= len;
|
||||||
}
|
}
|
||||||
@ -186,7 +181,8 @@ impl TextArea {
|
|||||||
|
|
||||||
fn fix_ghost_row(&mut self) {
|
fn fix_ghost_row(&mut self) {
|
||||||
if self.rows.is_empty() ||
|
if self.rows.is_empty() ||
|
||||||
self.rows.last().unwrap().end != self.content.len() {
|
self.rows.last().unwrap().end != self.content.len()
|
||||||
|
{
|
||||||
// Add a fake, empty row at the end.
|
// Add a fake, empty row at the end.
|
||||||
self.rows.push(Row {
|
self.rows.push(Row {
|
||||||
start: self.content.len(),
|
start: self.content.len(),
|
||||||
@ -312,10 +308,12 @@ impl TextArea {
|
|||||||
// We don't need to go beyond a newline.
|
// We don't need to go beyond a newline.
|
||||||
// If we don't find one, end of the text it is.
|
// If we don't find one, end of the text it is.
|
||||||
// println_stderr!("Cursor: {}", self.cursor);
|
// println_stderr!("Cursor: {}", self.cursor);
|
||||||
let last_byte = self.content[self.cursor..]
|
let last_byte = self.content[self.cursor..].find('\n').map(|i| {
|
||||||
.find('\n')
|
1 + i + self.cursor
|
||||||
.map(|i| 1 + i + self.cursor);
|
});
|
||||||
let last_row = last_byte.map_or(self.rows.len(), |last_byte| self.row_at(last_byte));
|
let last_row = last_byte.map_or(self.rows.len(), |last_byte| {
|
||||||
|
self.row_at(last_byte)
|
||||||
|
});
|
||||||
let last_byte = last_byte.unwrap_or_else(|| self.content.len());
|
let last_byte = last_byte.unwrap_or_else(|| self.content.len());
|
||||||
|
|
||||||
// println_stderr!("Content: `{}` (len={})",
|
// println_stderr!("Content: `{}` (len={})",
|
||||||
@ -335,13 +333,13 @@ impl TextArea {
|
|||||||
|
|
||||||
// First attempt, if scrollbase status didn't change.
|
// First attempt, if scrollbase status didn't change.
|
||||||
// println_stderr!("Rows: {:?}", self.rows);
|
// println_stderr!("Rows: {:?}", self.rows);
|
||||||
let new_rows = make_rows(&self.content[first_byte..last_byte],
|
let new_rows =
|
||||||
available);
|
make_rows(&self.content[first_byte..last_byte], available);
|
||||||
// How much did this add?
|
// How much did this add?
|
||||||
// println_stderr!("New rows: {:?}", new_rows);
|
// println_stderr!("New rows: {:?}", new_rows);
|
||||||
// println_stderr!("{}-{}", first_row, last_row);
|
// println_stderr!("{}-{}", first_row, last_row);
|
||||||
let new_row_count = self.rows.len() + new_rows.len() + first_row -
|
let new_row_count = self.rows.len() + new_rows.len() + first_row -
|
||||||
last_row;
|
last_row;
|
||||||
if !scrollable && new_row_count > size.y {
|
if !scrollable && new_row_count > size.y {
|
||||||
// We just changed scrollable status.
|
// We just changed scrollable status.
|
||||||
// This changes everything.
|
// This changes everything.
|
||||||
@ -354,8 +352,8 @@ impl TextArea {
|
|||||||
|
|
||||||
// Otherwise, replace stuff.
|
// Otherwise, replace stuff.
|
||||||
let affected_rows = first_row..last_row;
|
let affected_rows = first_row..last_row;
|
||||||
let replacement_rows = new_rows.into_iter()
|
let replacement_rows =
|
||||||
.map(|row| row.shifted(first_byte));
|
new_rows.into_iter().map(|row| row.shifted(first_byte));
|
||||||
VecExt::splice(&mut self.rows, affected_rows, replacement_rows);
|
VecExt::splice(&mut self.rows, affected_rows, replacement_rows);
|
||||||
self.fix_ghost_row();
|
self.fix_ghost_row();
|
||||||
self.scrollbase.set_heights(size.y, self.rows.len());
|
self.scrollbase.set_heights(size.y, self.rows.len());
|
||||||
@ -364,10 +362,17 @@ impl TextArea {
|
|||||||
|
|
||||||
impl View for TextArea {
|
impl View for TextArea {
|
||||||
fn required_size(&mut self, constraint: Vec2) -> Vec2 {
|
fn required_size(&mut self, constraint: Vec2) -> Vec2 {
|
||||||
|
// Make sure our structure is up to date
|
||||||
self.compute_rows(constraint);
|
self.compute_rows(constraint);
|
||||||
|
|
||||||
|
// Ideally, we'd want x = the longest row + 1
|
||||||
|
// (we always keep a space at the end)
|
||||||
|
// And y = number of rows
|
||||||
|
// println_stderr!("{:?}", self.rows);
|
||||||
|
let scroll_width = if self.rows.len() > constraint.y { 1 } else { 0 };
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
1 + self.rows.iter().map(|r| r.width).max().unwrap_or(1),
|
scroll_width + 1 + self.rows.iter().map(|r| r.width).max().unwrap_or(1),
|
||||||
self.rows.len()
|
self.rows.len(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,10 +389,12 @@ impl View for TextArea {
|
|||||||
} else {
|
} else {
|
||||||
printer.size.x
|
printer.size.x
|
||||||
};
|
};
|
||||||
printer.with_effect(effect,
|
printer.with_effect(
|
||||||
|printer| for y in 0..printer.size.y {
|
effect,
|
||||||
printer.print_hline((0, y), w, " ");
|
|printer| for y in 0..printer.size.y {
|
||||||
});
|
printer.print_hline((0, y), w, " ");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// println_stderr!("Content: `{}`", &self.content);
|
// println_stderr!("Content: `{}`", &self.content);
|
||||||
self.scrollbase.draw(printer, |printer, i| {
|
self.scrollbase.draw(printer, |printer, i| {
|
||||||
@ -396,19 +403,19 @@ impl View for TextArea {
|
|||||||
// println_stderr!("row: {:?}", row);
|
// println_stderr!("row: {:?}", row);
|
||||||
let text = &self.content[row.start..row.end];
|
let text = &self.content[row.start..row.end];
|
||||||
// println_stderr!("row text: `{}`", text);
|
// println_stderr!("row text: `{}`", text);
|
||||||
printer.with_effect(effect, |printer| {
|
printer.with_effect(
|
||||||
printer.print((0, 0), text);
|
effect,
|
||||||
});
|
|printer| { printer.print((0, 0), text); },
|
||||||
|
);
|
||||||
|
|
||||||
if printer.focused && i == self.selected_row() {
|
if printer.focused && i == self.selected_row() {
|
||||||
let cursor_offset = self.cursor - row.start;
|
let cursor_offset = self.cursor - row.start;
|
||||||
let c = if cursor_offset == text.len() {
|
let c = if cursor_offset == text.len() {
|
||||||
"_"
|
"_"
|
||||||
} else {
|
} else {
|
||||||
text[cursor_offset..]
|
text[cursor_offset..].graphemes(true).next().expect(
|
||||||
.graphemes(true)
|
"Found no char!",
|
||||||
.next()
|
)
|
||||||
.expect("Found no char!")
|
|
||||||
};
|
};
|
||||||
let offset = text[..cursor_offset].width();
|
let offset = text[..cursor_offset].width();
|
||||||
printer.print((offset, 0), c);
|
printer.print((offset, 0), c);
|
||||||
@ -431,7 +438,8 @@ impl View for TextArea {
|
|||||||
let row = self.selected_row();
|
let row = self.selected_row();
|
||||||
self.cursor = self.rows[row].end;
|
self.cursor = self.rows[row].end;
|
||||||
if row + 1 < self.rows.len() &&
|
if row + 1 < self.rows.len() &&
|
||||||
self.cursor == self.rows[row + 1].start {
|
self.cursor == self.rows[row + 1].start
|
||||||
|
{
|
||||||
self.move_left();
|
self.move_left();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,8 +449,10 @@ impl View for TextArea {
|
|||||||
self.cursor = self.rows[self.selected_row()].start
|
self.cursor = self.rows[self.selected_row()].start
|
||||||
}
|
}
|
||||||
Event::Key(Key::Up) if self.selected_row() > 0 => self.move_up(),
|
Event::Key(Key::Up) if self.selected_row() > 0 => self.move_up(),
|
||||||
Event::Key(Key::Down) if self.selected_row() + 1 <
|
Event::Key(Key::Down)
|
||||||
self.rows.len() => self.move_down(),
|
if self.selected_row() + 1 < self.rows.len() => {
|
||||||
|
self.move_down()
|
||||||
|
}
|
||||||
Event::Key(Key::PageUp) => self.page_up(),
|
Event::Key(Key::PageUp) => self.page_up(),
|
||||||
Event::Key(Key::PageDown) => self.page_down(),
|
Event::Key(Key::PageDown) => self.page_down(),
|
||||||
Event::Key(Key::Left) if self.cursor > 0 => self.move_left(),
|
Event::Key(Key::Left) if self.cursor > 0 => self.move_left(),
|
||||||
|
Loading…
Reference in New Issue
Block a user