Allow for undefined buffer width and/or height, fixes #70

This commit is contained in:
Jeremy Soller 2024-06-12 09:04:04 -06:00
parent cd1cd0a337
commit 93a7df859a
15 changed files with 99 additions and 72 deletions

View file

@ -129,8 +129,10 @@ impl<'b> Iterator for LayoutRunIter<'b> {
let glyph_height = layout_line.max_ascent + layout_line.max_descent;
let centering_offset = (line_height - glyph_height) / 2.0;
let line_y = line_top + centering_offset + layout_line.max_ascent;
if line_top + centering_offset > self.buffer.height {
return None;
if let Some(height) = self.buffer.height_opt {
if line_top + centering_offset > height {
return None;
}
}
self.line_top += line_height;
if line_y < 0.0 {
@ -203,8 +205,8 @@ pub struct Buffer {
/// [BufferLine]s (or paragraphs) of text in the buffer
pub lines: Vec<BufferLine>,
metrics: Metrics,
width: f32,
height: f32,
width_opt: Option<f32>,
height_opt: Option<f32>,
scroll: Scroll,
/// True if a redraw is requires. Set to false after processing
redraw: bool,
@ -221,8 +223,8 @@ impl Clone for Buffer {
Self {
lines: self.lines.clone(),
metrics: self.metrics,
width: self.width,
height: self.height,
width_opt: self.width_opt,
height_opt: self.height_opt,
scroll: self.scroll,
redraw: self.redraw,
wrap: self.wrap,
@ -250,8 +252,8 @@ impl Buffer {
Self {
lines: Vec::new(),
metrics,
width: 0.0,
height: 0.0,
width_opt: None,
height_opt: None,
scroll: Scroll::default(),
redraw: false,
wrap: Wrap::WordOrGlyph,
@ -294,7 +296,7 @@ impl Buffer {
&mut self.scratch,
font_system,
self.metrics.font_size,
Some(self.width),
self.width_opt,
self.wrap,
self.monospace_width,
self.tab_width,
@ -315,7 +317,6 @@ impl Buffer {
cursor: Cursor,
prune: bool,
) {
let height = self.height;
let metrics = self.metrics;
let old_scroll = self.scroll;
@ -345,7 +346,7 @@ impl Buffer {
// Adjust scroll backwards if cursor is before it
self.scroll.line = layout_cursor.line;
self.scroll.vertical = layout_y;
} else {
} else if let Some(height) = self.height_opt {
// Adjust scroll forwards if cursor is after it
let mut line_i = layout_cursor.line;
while line_i > self.scroll.line {
@ -389,9 +390,11 @@ impl Buffer {
self.scroll.horizontal = x_min;
self.redraw = true;
}
if x_max > self.scroll.horizontal + self.width {
self.scroll.horizontal = x_max - self.width;
self.redraw = true;
if let Some(width) = self.width_opt {
if x_max > self.scroll.horizontal + width {
self.scroll.horizontal = x_max - width;
self.redraw = true;
}
}
}
}
@ -424,7 +427,7 @@ impl Buffer {
}
let scroll_start = self.scroll.vertical;
let scroll_end = scroll_start + self.height;
let scroll_end = scroll_start + self.height_opt.unwrap_or(f32::INFINITY);
let mut total_height = 0.0;
for line_i in 0..self.lines.len() {
@ -528,7 +531,7 @@ impl Buffer {
&mut self.scratch,
font_system,
self.metrics.font_size,
Some(self.width),
self.width_opt,
self.wrap,
self.monospace_width,
self.tab_width,
@ -546,7 +549,7 @@ impl Buffer {
///
/// Will panic if `metrics.font_size` is zero.
pub fn set_metrics(&mut self, font_system: &mut FontSystem, metrics: Metrics) {
self.set_metrics_and_size(font_system, metrics, self.width, self.height);
self.set_metrics_and_size(font_system, metrics, self.width_opt, self.height_opt);
}
/// Get the current [`Wrap`]
@ -608,13 +611,18 @@ impl Buffer {
}
/// Get the current buffer dimensions (width, height)
pub fn size(&self) -> (f32, f32) {
(self.width, self.height)
pub fn size(&self) -> (Option<f32>, Option<f32>) {
(self.width_opt, self.height_opt)
}
/// Set the current buffer dimensions
pub fn set_size(&mut self, font_system: &mut FontSystem, width: f32, height: f32) {
self.set_metrics_and_size(font_system, self.metrics, width, height);
pub fn set_size(
&mut self,
font_system: &mut FontSystem,
width_opt: Option<f32>,
height_opt: Option<f32>,
) {
self.set_metrics_and_size(font_system, self.metrics, width_opt, height_opt);
}
/// Set the current [`Metrics`] and buffer dimensions at the same time
@ -626,17 +634,20 @@ impl Buffer {
&mut self,
font_system: &mut FontSystem,
metrics: Metrics,
width: f32,
height: f32,
width_opt: Option<f32>,
height_opt: Option<f32>,
) {
let clamped_width = width.max(0.0);
let clamped_height = height.max(0.0);
let clamped_width_opt = width_opt.map(|width| width.max(0.0));
let clamped_height_opt = height_opt.map(|height| height.max(0.0));
if metrics != self.metrics || clamped_width != self.width || clamped_height != self.height {
if metrics != self.metrics
|| clamped_width_opt != self.width_opt
|| clamped_height_opt != self.height_opt
{
assert_ne!(metrics.font_size, 0.0, "font size cannot be 0");
self.metrics = metrics;
self.width = clamped_width;
self.height = clamped_height;
self.width_opt = clamped_width_opt;
self.height_opt = clamped_height_opt;
self.relayout(font_system);
self.shape_until_scroll(font_system, false);
}
@ -1128,20 +1139,24 @@ impl Buffer {
cursor_x_opt = None;
}
Motion::PageUp => {
(cursor, cursor_x_opt) = self.cursor_motion(
font_system,
cursor,
cursor_x_opt,
Motion::Vertical(-self.size().1 as i32),
)?;
if let Some(height) = self.height_opt {
(cursor, cursor_x_opt) = self.cursor_motion(
font_system,
cursor,
cursor_x_opt,
Motion::Vertical(-height as i32),
)?;
}
}
Motion::PageDown => {
(cursor, cursor_x_opt) = self.cursor_motion(
font_system,
cursor,
cursor_x_opt,
Motion::Vertical(self.size().1 as i32),
)?;
if let Some(height) = self.height_opt {
(cursor, cursor_x_opt) = self.cursor_motion(
font_system,
cursor,
cursor_x_opt,
Motion::Vertical(height as i32),
)?;
}
}
Motion::Vertical(px) => {
// TODO more efficient, use layout run line height
@ -1341,8 +1356,8 @@ impl<'a> BorrowedWithFontSystem<'a, Buffer> {
}
/// Set the current buffer dimensions
pub fn set_size(&mut self, width: f32, height: f32) {
self.inner.set_size(self.font_system, width, height);
pub fn set_size(&mut self, width_opt: Option<f32>, height_opt: Option<f32>) {
self.inner.set_size(self.font_system, width_opt, height_opt);
}
/// Set the current [`Metrics`] and buffer dimensions at the same time
@ -1350,9 +1365,14 @@ impl<'a> BorrowedWithFontSystem<'a, Buffer> {
/// # Panics
///
/// Will panic if `metrics.font_size` is zero.
pub fn set_metrics_and_size(&mut self, metrics: Metrics, width: f32, height: f32) {
pub fn set_metrics_and_size(
&mut self,
metrics: Metrics,
width_opt: Option<f32>,
height_opt: Option<f32>,
) {
self.inner
.set_metrics_and_size(self.font_system, metrics, width, height);
.set_metrics_and_size(self.font_system, metrics, width_opt, height_opt);
}
/// Set text of buffer, using provided attributes for each line by default