ElyTable: a cell scrolls in by the least amount; a drag never scrolls under the pointer (T-02)

This commit is contained in:
ZacharyZhang-NY committed 2026-10-09 09:47:10 -04:00
1 parent c52e1a3b16
commit ecf977364b
6 files changed
+31 -6

No files matched your search

+3 -1
View File
@@ -375,8 +375,9 @@ impl LokView {
}
if batch.cursor != self.cursor {
self.moves += 1;
// A moved cursor stays in view.
// A moved cursor stays in view, but not mid-drag.
if self.viewport.1 > 0.0
&& !self.dragging
&& let Some(cursor) = batch.cursor
{
self.show(cursor, cx);
@@ -385,6 +386,7 @@ impl LokView {
// A moved cell cursor stays in view too.
if batch.cell.cursor != self.cell.cursor
&& self.viewport.1 > 0.0
&& !self.dragging
&& let Some(cell) = batch.cell.cursor
{
self.show(cell, cx);
+11 -4
View File
@@ -61,11 +61,11 @@ impl LokView {
let need = self.print_of((x + w + vw + fx, y + h + vh + fy));
self.reach = (self.reach.0.max(need.0), self.reach.1.max(need.1));
}
if x >= fx && (x < fx + self.scroll.0 || x + w > fx + self.scroll.0 + vw) {
self.scroll.0 = x - fx - vw / 2;
if x >= fx {
self.scroll.0 = least(x - fx, w, self.scroll.0, vw);
}
if y >= fy && (y < fy + self.scroll.1 || y + h > fy + self.scroll.1 + vh) {
self.scroll.1 = y - fy - vh / 3;
if y >= fy {
self.scroll.1 = least(y - fy, h, self.scroll.1, vh);
}
self.clamp_scroll();
cx.notify();
@@ -172,3 +172,10 @@ impl LokView {
})
}
}
/// The scroll nearest `scroll` that shows `start..start + len`.
fn least(start: i32, len: i32, scroll: i32, view: i32) -> i32 {
// A span wider than the view keeps covering it.
let end = start + len - view;
scroll.clamp(start.min(end), start.max(end))
}
+10
View File
@@ -202,6 +202,16 @@ fn a_sheet_brings_far_cut_and_frozen_cells_into_view() {
let cut = (width - 200, 0, 1280, 256);
view.show(cut, cx);
assert!(view.scroll.0 > 0 && shows(view, cut), "a cell cut at the right edge comes into view");
let (x, _, w, _) = view.tile_rect(cut);
assert_eq!(view.scroll.0, x + w - width, "it scrolls no further than the cell's edge");
let before = view.scroll;
view.show((0, 0, view.print_of((x + w + width, 0)).0, 256), cx);
assert_eq!(view.scroll, before, "a cell wider than the view and covering it keeps still");
view.dragging = true;
let cell = crate::Cell { cursor: Some((1418, 90_000, 1280, 277)), ..crate::Cell::default() };
view.apply_batch(crate::Events { cell, ..crate::Events::default() }, None, cx);
assert_eq!(view.scroll, before, "a drag does not scroll under the pointer");
view.dragging = false;
view.scroll = (0, 0);
view.set_frozen((0, 600), cx);
let frozen = view.place((0, 300)).y;
+1 -1
View File
@@ -3,7 +3,7 @@
`docs/BugList.md` 的 93 条,按清单次序逐条处理:先核对当前代码,已由先前改动修好的写明出处,其余修好、审查、提交、推送后勾上。
- [x] T-01 内核的图块与命中按像素网格,Ely 的光标、选区、表头按文档 twips,越远越错位 — R2.16 已修(图块 twips 与打印 twips 互换)
- [ ] T-02 单元格光标露出边缘即把视图滚到中央,点击与拖选时视图跳动
- [x] T-02 单元格光标露出边缘即把视图滚到中央,点击与拖选时视图跳动 — R1 拖选中仍滚、超宽格跳回起点;R2 PASS
- [ ] T-03 视口比工作表宽时网格先居中再左移一次
- [x] T-04 从不调用 `setClientZoom`,内核命中与几何按默认缩放算 — R2.16 已修(worker 每次报可见区前 setClientZoom)
- [ ] T-05 文档尺寸按内核像素取整,表尾被裁
+5
View File
@@ -0,0 +1,5 @@
FAIL
crates/ely-lok/src/view/scroll.rs:64 — `show()` 在鼠标按下、`dragging=true` 时仍根据单元格光标调整滚动,拖选坐标随回调改变,违反 docs/BugList.md T-02 的拖选要求及 PRD TABLE-02、LOK-04。真实 LOK 探针使用 large.rs 的 SHORT_ROWS、100% 缩放、200×70 像素视口:在 (180,65) 按下 C4,等待光标回调,再拖到原画面 B3 所在的 (130,40) 并释放;按下后的 scroll 从 (0,0) 变成 (824,29),最终选区为 C3:C4,预期为 B3:C4,连续两次复现。large.rs:145 的现有拖选测试在同一次 update 中发送全部鼠标事件,覆盖不到这次中途滚动。修复方向:拖选期间保持视图坐标稳定,保留键盘导航的最小滚动;回归测试在按下与移动之间等待内核回调,并核对滚动与最终选区。副本中抑制拖选期间的自动滚动后,此探针通过。
crates/ely-lok/src/view/scroll.rs:178 — 超出视口尺寸的目标总被对齐到起点,视口已处于单元格内部时仍大幅跳动,T-02 的最小滚动要求在超宽列上仍失败。真实 LOK 探针设置 A 列宽 20 cm、视口 400×200 像素、100% 缩放,横向 scroll=4500 twips(300 像素);A2 的图块横向区间为 0..11325 twips,完整覆盖当前视口 4500..10500。在 (50,30) 点击当前可见的 A2 后,scroll 立即归零,画面左跳 300 像素,连续两次复现。修复方向:目标大于视口且覆盖当前可视区时保持当前位置,其余情况采用最小必要位移;补充超宽列及超高行的回归断言。副本中保留这种已覆盖视口的位置后,此探针通过。
+1
View File
@@ -0,0 +1 @@
PASS