fix(editor): use page row height for pages-region scroll window
The Pages and Layers regions use different row heights (32px vs 28px), but visible_row_range / row_index_at hardcoded LAYER_ROW_HEIGHT for both. With a long page list scrolled toward the bottom, the pages window started at the wrong index — only the last page rendered and the rows above it were skipped, leaving a blank gap. Thread the region's row height through both helpers.
This commit is contained in:
parent
7536627056
commit
ec45fd99c1
|
|
@ -265,6 +265,7 @@ impl LayerPanel {
|
|||
r.layers_rows_top,
|
||||
r.layers.offset,
|
||||
r.layers_view_h,
|
||||
LAYER_ROW_HEIGHT,
|
||||
point.y,
|
||||
) {
|
||||
let item = &self.items[index];
|
||||
|
|
@ -341,6 +342,7 @@ impl LayerPanel {
|
|||
r.pages_rows_top,
|
||||
r.pages.offset,
|
||||
r.pages_view_h,
|
||||
PAGE_ROW_HEIGHT,
|
||||
point.y,
|
||||
) {
|
||||
let page = &self.pages[index];
|
||||
|
|
@ -371,6 +373,7 @@ impl LayerPanel {
|
|||
r.layers_rows_top,
|
||||
r.layers.offset,
|
||||
r.layers_view_h,
|
||||
LAYER_ROW_HEIGHT,
|
||||
point.y,
|
||||
) {
|
||||
let item = &self.items[index];
|
||||
|
|
@ -507,7 +510,12 @@ impl Widget for LayerPanel {
|
|||
origin: Point2D::new(rect.origin.x, r.pages_rows_top),
|
||||
size: Point2D::new(rect.size.x, r.pages_view_h),
|
||||
});
|
||||
for index in visible_row_range(self.pages.len(), r.pages.offset, r.pages_view_h) {
|
||||
for index in visible_row_range(
|
||||
self.pages.len(),
|
||||
r.pages.offset,
|
||||
r.pages_view_h,
|
||||
PAGE_ROW_HEIGHT,
|
||||
) {
|
||||
let page = &self.pages[index];
|
||||
y = r.pages_rows_top - r.pages.offset + index as f32 * PAGE_ROW_HEIGHT;
|
||||
let row = Rect {
|
||||
|
|
@ -595,7 +603,12 @@ impl Widget for LayerPanel {
|
|||
origin: Point2D::new(rect.origin.x, r.layers_rows_top),
|
||||
size: Point2D::new(rect.size.x, r.layers_view_h),
|
||||
});
|
||||
for index in visible_row_range(self.items.len(), r.layers.offset, r.layers_view_h) {
|
||||
for index in visible_row_range(
|
||||
self.items.len(),
|
||||
r.layers.offset,
|
||||
r.layers_view_h,
|
||||
LAYER_ROW_HEIGHT,
|
||||
) {
|
||||
let item = &self.items[index];
|
||||
y = r.layers_rows_top - r.layers.offset + index as f32 * LAYER_ROW_HEIGHT;
|
||||
let row = Rect {
|
||||
|
|
|
|||
|
|
@ -585,7 +585,12 @@ fn layer_panel_caches_content_widths_on_build() {
|
|||
|
||||
#[test]
|
||||
fn visible_row_range_jumps_directly_to_scrolled_rows() {
|
||||
let range = visible_row_range(1_000, LAYER_ROW_HEIGHT * 500.0, LAYER_ROW_HEIGHT * 10.0);
|
||||
let range = visible_row_range(
|
||||
1_000,
|
||||
LAYER_ROW_HEIGHT * 500.0,
|
||||
LAYER_ROW_HEIGHT * 10.0,
|
||||
LAYER_ROW_HEIGHT,
|
||||
);
|
||||
|
||||
assert_eq!(range.start, 500);
|
||||
assert!(
|
||||
|
|
@ -600,9 +605,55 @@ fn row_index_at_maps_scrolled_point_to_item_without_linear_scan() {
|
|||
let scroll = LAYER_ROW_HEIGHT * 500.0;
|
||||
let point_y = rows_top + LAYER_ROW_HEIGHT * 2.5;
|
||||
|
||||
let (index, row_top) = row_index_at(1_000, rows_top, scroll, LAYER_ROW_HEIGHT * 10.0, point_y)
|
||||
.expect("point lands on a visible row");
|
||||
let (index, row_top) = row_index_at(
|
||||
1_000,
|
||||
rows_top,
|
||||
scroll,
|
||||
LAYER_ROW_HEIGHT * 10.0,
|
||||
LAYER_ROW_HEIGHT,
|
||||
point_y,
|
||||
)
|
||||
.expect("point lands on a visible row");
|
||||
|
||||
assert_eq!(index, 502);
|
||||
assert!((row_top - (rows_top + LAYER_ROW_HEIGHT * 2.0)).abs() < 0.01);
|
||||
}
|
||||
|
||||
/// Pages rows are 32 px tall; the visible-row window and hit-test must
|
||||
/// use PAGE_ROW_HEIGHT, not the 28 px layer height. With 45 pages
|
||||
/// scrolled near the bottom, the window must still start at the row
|
||||
/// whose top the offset lands on — using the wrong height skips rows
|
||||
/// and leaves a blank gap above the last page.
|
||||
#[test]
|
||||
fn pages_visible_range_uses_page_row_height() {
|
||||
// Scroll so the top of row 39 is at the viewport top.
|
||||
let scroll = PAGE_ROW_HEIGHT * 39.0;
|
||||
let range = visible_row_range(45, scroll, PAGE_ROW_HEIGHT * 6.0, PAGE_ROW_HEIGHT);
|
||||
assert_eq!(
|
||||
range.start, 39,
|
||||
"pages window must start at the 32px-row index, got {range:?}"
|
||||
);
|
||||
assert!(
|
||||
range.end >= 45,
|
||||
"window must reach the last page, got {range:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pages_hit_test_uses_page_row_height() {
|
||||
let rows_top = 60.0;
|
||||
let scroll = PAGE_ROW_HEIGHT * 39.0;
|
||||
// Cursor 2.5 rows down from the viewport top → row 41.
|
||||
let point_y = rows_top + PAGE_ROW_HEIGHT * 2.5;
|
||||
let (index, row_top) = row_index_at(
|
||||
45,
|
||||
rows_top,
|
||||
scroll,
|
||||
PAGE_ROW_HEIGHT * 6.0,
|
||||
PAGE_ROW_HEIGHT,
|
||||
point_y,
|
||||
)
|
||||
.expect("point lands on a page row");
|
||||
assert_eq!(index, 41, "hit-test must map to the 32px-row index");
|
||||
assert!((row_top - (rows_top + PAGE_ROW_HEIGHT * 2.0)).abs() < 0.01);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -409,12 +409,13 @@ pub(super) fn visible_row_range(
|
|||
row_count: usize,
|
||||
scroll: f32,
|
||||
viewport_h: f32,
|
||||
row_height: f32,
|
||||
) -> std::ops::Range<usize> {
|
||||
if row_count == 0 || viewport_h <= 0.0 {
|
||||
if row_count == 0 || viewport_h <= 0.0 || row_height <= 0.0 {
|
||||
return 0..0;
|
||||
}
|
||||
let start = (scroll.max(0.0) / LAYER_ROW_HEIGHT).floor() as usize;
|
||||
let visible = (viewport_h / LAYER_ROW_HEIGHT).ceil().max(0.0) as usize;
|
||||
let start = (scroll.max(0.0) / row_height).floor() as usize;
|
||||
let visible = (viewport_h / row_height).ceil().max(0.0) as usize;
|
||||
let end = start
|
||||
.saturating_add(visible)
|
||||
.saturating_add(2)
|
||||
|
|
@ -429,9 +430,10 @@ pub(super) fn row_index_at(
|
|||
rows_top: f32,
|
||||
scroll: f32,
|
||||
viewport_h: f32,
|
||||
row_height: f32,
|
||||
point_y: f32,
|
||||
) -> Option<(usize, f32)> {
|
||||
if row_count == 0 || viewport_h <= 0.0 {
|
||||
if row_count == 0 || viewport_h <= 0.0 || row_height <= 0.0 {
|
||||
return None;
|
||||
}
|
||||
if point_y < rows_top || point_y > rows_top + viewport_h {
|
||||
|
|
@ -441,10 +443,10 @@ pub(super) fn row_index_at(
|
|||
if local_y < 0.0 {
|
||||
return None;
|
||||
}
|
||||
let index = (local_y / LAYER_ROW_HEIGHT).floor() as usize;
|
||||
let index = (local_y / row_height).floor() as usize;
|
||||
if index >= row_count {
|
||||
return None;
|
||||
}
|
||||
let row_top = rows_top - scroll.max(0.0) + index as f32 * LAYER_ROW_HEIGHT;
|
||||
let row_top = rows_top - scroll.max(0.0) + index as f32 * row_height;
|
||||
Some((index, row_top))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue