ElyTable: a sheet starts at the left, even before its geometry arrives (T-03)
This commit is contained in:
8 files changed
+43
-10
No files matched your search
@@ -73,9 +73,16 @@ pub struct Doc {
|
||||
id: u64,
|
||||
/// The document's revision when this handle was taken.
|
||||
pub(crate) rev: u64,
|
||||
/// LOK_DOCTYPE: 0 text, 1 spreadsheet, 2 presentation.
|
||||
kind: u64,
|
||||
}
|
||||
|
||||
impl Doc {
|
||||
/// Whether this is a spreadsheet.
|
||||
pub fn is_sheet(&self) -> bool {
|
||||
self.kind == 1
|
||||
}
|
||||
|
||||
/// Whether this handle saw a later state than `other`.
|
||||
pub fn newer_than(&self, other: &Doc) -> bool {
|
||||
self.rev > other.rev
|
||||
@@ -217,9 +224,10 @@ impl Worker {
|
||||
pack.u64(at(COLUMNS.iter().position(|c| c == column)))
|
||||
});
|
||||
let payload = self.request(tag::IMPORT, &pack.bytes())?;
|
||||
let id = Unpack::new(&payload).u64()?;
|
||||
let mut reply = Unpack::new(&payload);
|
||||
let (id, kind) = (reply.u64()?, reply.u64()?);
|
||||
self.feed.opened(id);
|
||||
Ok(Doc { worker: self.session, id, rev: 0 })
|
||||
Ok(Doc { worker: self.session, id, rev: 0, kind })
|
||||
}
|
||||
|
||||
/// Loads `url` with its password; a locked one is PermissionDenied.
|
||||
@@ -232,9 +240,10 @@ impl Worker {
|
||||
error
|
||||
}
|
||||
})?;
|
||||
let id = Unpack::new(&payload).u64()?;
|
||||
let mut reply = Unpack::new(&payload);
|
||||
let (id, kind) = (reply.u64()?, reply.u64()?);
|
||||
self.feed.opened(id);
|
||||
Ok(Doc { worker: self.session, id, rev: 0 })
|
||||
Ok(Doc { worker: self.session, id, rev: 0, kind })
|
||||
}
|
||||
|
||||
/// Runs a macro by its URL (LOK-11 probe).
|
||||
|
||||
@@ -181,17 +181,17 @@ mod tests {
|
||||
};
|
||||
feed.push(1, first);
|
||||
feed.push(1, second);
|
||||
let batch = feed.wait(&Doc { worker: 0, id: 1, rev: 0 }, 0, 0).expect("a batch");
|
||||
let batch = feed.wait(&Doc { worker: 0, id: 1, rev: 0, kind: 0 }, 0, 0).expect("a batch");
|
||||
assert_eq!((batch.seq, batch.all, batch.rects.len()), (2, true, 1));
|
||||
assert_eq!(
|
||||
batch.states,
|
||||
[("b".to_string(), "1".to_string()), ("a".into(), "2".into())]
|
||||
);
|
||||
let idle = feed.wait(&Doc { worker: 0, id: 1, rev: 0 }, 2, 0).expect("the snapshot");
|
||||
let idle = feed.wait(&Doc { worker: 0, id: 1, rev: 0, kind: 0 }, 2, 0).expect("the snapshot");
|
||||
assert!(idle.rects.is_empty() && idle.states.is_empty() && idle.seq == 2);
|
||||
feed.closed(1);
|
||||
assert!(
|
||||
feed.wait(&Doc { worker: 0, id: 1, rev: 0 }, 2, 0).is_err(),
|
||||
feed.wait(&Doc { worker: 0, id: 1, rev: 0, kind: 0 }, 2, 0).is_err(),
|
||||
"a closed document"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -251,6 +251,10 @@ impl LokView {
|
||||
|
||||
/// Room beside a narrow document, which sits centred.
|
||||
pub(super) fn slack(&self) -> (f32, f32) {
|
||||
// A sheet's grid grows with the view; it starts left.
|
||||
if self.doc.is_sheet() {
|
||||
return (0.0, 0.0);
|
||||
}
|
||||
let extent = self.extent();
|
||||
let slack = |view: f32, doc: i32| (view - self.geom.px_of(doc)).max(0.0) / 2.0;
|
||||
// A fitted page sits centred both ways.
|
||||
|
||||
@@ -186,7 +186,12 @@ fn a_sheet_brings_far_cut_and_frozen_cells_into_view() {
|
||||
let (view, worker) = live_view_of(app, &install, "short.fods", SHORT_ROWS);
|
||||
let json = worker.lock().expect("the worker lock").values(&view.read(app).doc, crate::sheet::GEOMETRY).expect("geometry");
|
||||
view.update(app, |view, cx| {
|
||||
let wide = Bounds { origin: point(px(0.0), px(0.0)), size: size(px(6000.0), px(200.0)) };
|
||||
view.prepare(wide);
|
||||
assert_eq!(view.spare, (0.0, 0.0), "before its geometry a sheet starts left");
|
||||
view.set_geometry(crate::sheet::geometry(&json).expect("parsed"), cx);
|
||||
view.prepare(wide);
|
||||
assert_eq!(view.spare, (0.0, 0.0), "and stays left after it");
|
||||
view.viewport = (800.0, 200.0);
|
||||
let (width, height) = (view.geom.twips_of(view.viewport.0), view.geom.twips_of(view.viewport.1));
|
||||
let shows = |view: &LokView, rect: crate::Rect| {
|
||||
|
||||
@@ -187,8 +187,8 @@ fn answer(lok: &Lok, tag: u8, id: u64, payload: &[u8]) {
|
||||
.str()
|
||||
.and_then(|url| Ok((url, unpack.str()?)))
|
||||
.and_then(|(url, password)| load(lok, &url, password, ""))
|
||||
.map(|id| Pack::new().u64(id).bytes()),
|
||||
tag::IMPORT => text::import(lok, unpack).map(|id| Pack::new().u64(id).bytes()),
|
||||
.and_then(loaded),
|
||||
tag::IMPORT => text::import(lok, unpack).and_then(loaded),
|
||||
tag::EXPORT_TEXT => text::export(unpack).map(|()| Vec::new()),
|
||||
tag::DOC_SIZE => unpack
|
||||
.u64()
|
||||
@@ -339,6 +339,12 @@ fn load(lok: &Lok, url: &str, password: String, filter: &str) -> io::Result<u64>
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// The reply to a load: the number and LOK_DOCTYPE.
|
||||
fn loaded(id: u64) -> io::Result<Vec<u8>> {
|
||||
let kind = with_doc(id, |doc| doc.kind())?;
|
||||
Ok(Pack::new().u64(id).u64(kind as u64).bytes())
|
||||
}
|
||||
|
||||
/// Stops watching and frees document `id`.
|
||||
fn close(id: u64) {
|
||||
let mut docs = docs().lock().expect("the docs lock");
|
||||
|
||||
+6
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
- [x] T-01 内核的图块与命中按像素网格,Ely 的光标、选区、表头按文档 twips,越远越错位 — R2.16 已修(图块 twips 与打印 twips 互换)
|
||||
- [x] T-02 单元格光标露出边缘即把视图滚到中央,点击与拖选时视图跳动 — R1 拖选中仍滚、超宽格跳回起点;R2 PASS
|
||||
- [ ] T-03 视口比工作表宽时网格先居中再左移一次
|
||||
- [x] T-03 视口比工作表宽时网格先居中再左移一次 — 载入回复带文档种类,表格不居中;R1 测试漏几何到达前的首帧;R2 PASS
|
||||
- [x] T-04 从不调用 `setClientZoom`,内核命中与几何按默认缩放算 — R2.16 已修(worker 每次报可见区前 setClientZoom)
|
||||
- [ ] T-05 文档尺寸按内核像素取整,表尾被裁
|
||||
- [ ] T-06 滚轮向下被内核平铺区卡住
|
||||
@@ -95,3 +95,8 @@
|
||||
- [ ] X-12 恢复路径在界面线程做文件 I/O
|
||||
- [ ] X-13 非 macOS 构建里仍提供只会报“未构建”的入口
|
||||
- [ ] X-14 `agents.md` 引用的 `docs/engineering-risks.md` 不存在
|
||||
|
||||
## 0.1.2 发布
|
||||
|
||||
- [ ] REL-1 dmg 里有指向“应用程序”的快捷方式,可直接拖入安装(用户 2026-10-09 报)
|
||||
- [ ] REL-2 修完上列各条后打包、发布 0.1.2,官网指向新发布页
|
||||
@@ -0,0 +1,3 @@
|
||||
FAIL
|
||||
|
||||
crates/ely-lok/src/view/tests/large.rs:189 — T-03 回归测试遗漏几何数据到达前的首次绘制。测试先调用 set_geometry,再准备宽视口,因此允许依赖几何就绪的实现通过。具体复现:在隔离副本中将 render.rs:255 的 self.doc.is_sheet() 改成 self.sheet.is_some(),现有 a_sheet_brings_far_cut_and_frozen_cells_into_view 仍通过;对同一 short.fods 在 set_geometry 前绘制 6000×200 视口,首块原点从应有的 (10,20) 变成 (2123.5667,20),横向偏移 2113.5667 像素。ElyTable 的几何由 book.rs 的 reread 异步读取,这个首帧窗口对应实际加载路径。恢复原实现后,同一首帧探针通过。修复方向:在 set_geometry 前加入宽视口首帧断言,核对首块的实际绘制位置和命中坐标;几何到达后再次核对位置稳定。证据:/tmp/ely-t03-mutant-late.log、/tmp/ely-t03-firstframe-mutant.log、/tmp/ely-t03-firstframe-baseline.log。
|
||||
@@ -0,0 +1 @@
|
||||
PASS
|
||||
Reference in new issue
Block a user