ElyTable: clicks and drags land on the cell under them far down a sheet (R2.16)
This commit is contained in:
15 files changed
+297
-33
No files matched your search
@@ -55,14 +55,16 @@ impl Doc {
|
||||
Ok(Sheets { current, list })
|
||||
}
|
||||
|
||||
/// Tells the kernel the area the view shows, in twips.
|
||||
pub fn visible_area(&self, worker: &mut Worker, (x, y, w, h): Rect) -> io::Result<()> {
|
||||
/// Tells the kernel the shown area and the tile scale.
|
||||
pub fn visible_area(&self, worker: &mut Worker, (x, y, w, h): Rect, (tile, tile_twips): (u32, i32)) -> io::Result<()> {
|
||||
let request = Pack::new()
|
||||
.u64(worker.doc_id(self)?)
|
||||
.i64(x.into())
|
||||
.i64(y.into())
|
||||
.i64(w.into())
|
||||
.i64(h.into())
|
||||
.i64(tile.into())
|
||||
.i64(tile_twips.into())
|
||||
.bytes();
|
||||
worker.request(tag::VISIBLE_AREA, &request)?;
|
||||
Ok(())
|
||||
|
||||
@@ -485,3 +485,29 @@ fn enter_and_tab_move_the_cell_cursor() {
|
||||
});
|
||||
assert_eq!(right.cell.address, "G2", "Tab moves right");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_click_far_down_selects_the_cell_under_it() {
|
||||
if skip() {
|
||||
return;
|
||||
}
|
||||
let (_dir, mut worker, doc, seen) = open();
|
||||
// One painted tile fixes the kernel's scale.
|
||||
let (side, twips) = (512u32, 3840);
|
||||
let ppt = f64::from(side) / f64::from(twips);
|
||||
doc.paint_tile(&mut worker, (0, 0, twips, twips), (side, side)).expect("a tile");
|
||||
let geometry = sheet::geometry(&worker.values(&doc, sheet::GEOMETRY).expect("geometry")).expect("parsed");
|
||||
worker.run(&doc, "cell.goto", &["B4998"]).expect("B4998");
|
||||
let at = poll_until(&mut worker, &doc, &seen, SETTLE, |seen| seen.cell.address == "B4998");
|
||||
let (x, y, w, h) = at.cell.cursor.expect("the cursor");
|
||||
worker.run(&doc, "cell.goto", &["A1"]).expect("A1");
|
||||
let home = poll_until(&mut worker, &doc, &at, SETTLE, |seen| seen.cell.address == "A1");
|
||||
// The cursor is in print twips; clicks take tile twips.
|
||||
let (x, y) = (geometry.columns.tile(x + w / 2, ppt), geometry.rows.tile(y + h / 2, ppt));
|
||||
for kind in [0, 1] {
|
||||
let click = crate::Mouse { kind, x, y, count: 1, buttons: 1, modifiers: 0 };
|
||||
worker.post_mouse(&doc, click).expect("clicks");
|
||||
}
|
||||
let after = poll_until(&mut worker, &doc, &home, SETTLE, |seen| seen.cell.address != "A1");
|
||||
assert_eq!(after.cell.address, "B4998");
|
||||
}
|
||||
@@ -176,7 +176,7 @@ pub(super) fn open_book(text: &str) -> (tempfile::TempDir, Worker, Doc) {
|
||||
let doc = worker
|
||||
.load(&format!("file://{}", source.display()))
|
||||
.expect("the book loads");
|
||||
doc.visible_area(&mut worker, (0, 0, 15000, 10000))
|
||||
doc.visible_area(&mut worker, (0, 0, 15000, 10000), (256, 3840))
|
||||
.expect("the area");
|
||||
(dir, worker, doc)
|
||||
}
|
||||
@@ -247,6 +247,13 @@ impl Document {
|
||||
call!(class, 69, F, self.doc, view, true);
|
||||
}
|
||||
|
||||
/// Tells the kernel a tile's size in pixels and twips.
|
||||
pub fn set_client_zoom(&self, pixels: i32, twips: i32) {
|
||||
let class = unsafe { (*self.doc).class };
|
||||
type F = unsafe extern "C" fn(*mut Doc, i32, i32, i32, i32);
|
||||
call!(class, 23, F, self.doc, pixels, pixels, twips, twips);
|
||||
}
|
||||
|
||||
/// Tells the kernel the area the client shows, in twips.
|
||||
pub fn set_visible_area(&self, x: i32, y: i32, width: i32, height: i32) {
|
||||
let class = unsafe { (*self.doc).class };
|
||||
|
||||
@@ -71,6 +71,66 @@ impl Axis {
|
||||
}
|
||||
}
|
||||
|
||||
impl Axis {
|
||||
/// Where `index` starts in tile pixels.
|
||||
fn tile_start(&self, index: u32, ppt: f64) -> i64 {
|
||||
let (mut at, mut first) = (0i64, 0u32);
|
||||
for &(last, size) in &self.runs {
|
||||
let pixels = i64::from(to_pixels(size, ppt));
|
||||
if index <= last {
|
||||
return at + i64::from(index - first) * pixels;
|
||||
}
|
||||
at += i64::from(last - first + 1) * pixels;
|
||||
first = last + 1;
|
||||
}
|
||||
at
|
||||
}
|
||||
|
||||
/// A print-twips position in tile twips at `ppt`.
|
||||
pub fn tile(&self, print: i32, ppt: f64) -> i32 {
|
||||
let end = self.start(self.count());
|
||||
if print >= end {
|
||||
return clamp(twips_of(self.tile_start(self.count(), ppt), ppt) + i64::from(print - end));
|
||||
}
|
||||
let index = self.at(print);
|
||||
let (from, size) = (self.start(index), self.size(index));
|
||||
let start = twips_of(self.tile_start(index, ppt), ppt);
|
||||
let span = twips_of(self.tile_start(index + 1, ppt), ppt) - start;
|
||||
clamp(start + i64::from(print - from) * span / i64::from(size))
|
||||
}
|
||||
|
||||
/// The print-twips position under tile twips `tile`.
|
||||
pub fn print(&self, tile: i32, ppt: f64) -> i32 {
|
||||
let pixel = (f64::from(tile.max(0)) * ppt) as i64;
|
||||
let (mut at, mut first) = (0i64, 0u32);
|
||||
for &(last, size) in &self.runs {
|
||||
let pixels = i64::from(to_pixels(size, ppt));
|
||||
let span = i64::from(last - first + 1) * pixels;
|
||||
if pixels > 0 && pixel < at + span {
|
||||
let index = first + u32::try_from((pixel - at) / pixels).expect("inside a run");
|
||||
let start = twips_of(self.tile_start(index, ppt), ppt);
|
||||
let width = twips_of(self.tile_start(index + 1, ppt), ppt) - start;
|
||||
let into = i64::from(tile) - start;
|
||||
return clamp(i64::from(self.start(index)) + into * i64::from(size) / width.max(1));
|
||||
}
|
||||
at += span;
|
||||
first = last + 1;
|
||||
}
|
||||
let end = twips_of(self.tile_start(self.count(), ppt), ppt);
|
||||
clamp(i64::from(self.start(self.count())) + i64::from(tile) - end)
|
||||
}
|
||||
}
|
||||
|
||||
/// The kernel's `ScViewData::ToPixel`: truncates, never to 0.
|
||||
fn to_pixels(twips: i32, ppt: f64) -> i32 {
|
||||
let pixels = (f64::from(twips) * ppt) as i32;
|
||||
if pixels == 0 && twips != 0 { 1 } else { pixels }
|
||||
}
|
||||
|
||||
fn twips_of(pixels: i64, ppt: f64) -> i64 {
|
||||
(pixels as f64 / ppt).round() as i64
|
||||
}
|
||||
|
||||
fn clamp(twips: i64) -> i32 {
|
||||
i32::try_from(twips).unwrap_or(i32::MAX)
|
||||
}
|
||||
@@ -371,4 +431,29 @@ mod tests {
|
||||
assert_eq!(flags("1:2 5").expect("flags"), [(2, 1), (5, 0)]);
|
||||
assert!(merge(&[(3, 10)], &[(5, 0)]).is_err(), "lengths must agree");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tiles_round_each_row_to_whole_pixels() {
|
||||
// 293 twips at 2/15 px per twip truncate to 39.
|
||||
let rows = Axis { runs: vec![(9999, 293)] };
|
||||
let ppt = 2.0 / 15.0;
|
||||
assert_eq!(to_pixels(293, ppt), 39);
|
||||
let row = 4997u32;
|
||||
let print = rows.start(row);
|
||||
let tile = rows.tile(print, ppt);
|
||||
assert_eq!(tile, (f64::from(39 * row) / ppt).round() as i32, "row tops line up");
|
||||
assert_eq!(rows.print(tile, ppt), print, "and come back");
|
||||
let mid = rows.tile(print + 146, ppt);
|
||||
assert_eq!(rows.at(rows.print(mid, ppt)), row, "a point inside stays in its row");
|
||||
assert!(tile < print, "rounding down pulls far rows up");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hidden_rows_take_no_tile_space_and_tiny_rows_take_a_pixel() {
|
||||
let rows = Axis { runs: vec![(1, 300), (3, 0), (4, 3)] };
|
||||
let ppt = 1.0 / 15.0;
|
||||
assert_eq!(rows.tile(rows.start(4), ppt), rows.tile(rows.start(2), ppt), "hidden rows fold");
|
||||
assert_eq!(to_pixels(3, ppt), 1, "never 0 for a shown row");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,6 +28,7 @@ mod render;
|
||||
mod zoom;
|
||||
pub use zoom::{ZOOM_STEPS, Zoomed};
|
||||
mod scroll;
|
||||
mod sheet;
|
||||
pub use input::{CONTEXT, Copy, Cut, Paste, init};
|
||||
pub use off::read_off;
|
||||
pub use render::scheme;
|
||||
@@ -89,13 +90,15 @@ pub struct LokView {
|
||||
fetching: HashSet<(i32, i32)>,
|
||||
failed: HashSet<((i32, i32), u64)>,
|
||||
/// The area last told to the kernel.
|
||||
shown: Option<Rect>,
|
||||
shown: Option<(Rect, (u32, i32))>,
|
||||
viewport: (f32, f32),
|
||||
origin: Point<Pixels>,
|
||||
/// Pixels a small document sits in: left, top.
|
||||
spare: (f32, f32),
|
||||
/// Frozen columns and rows, in twips from the top left.
|
||||
frozen: (i32, i32),
|
||||
/// A spreadsheet's rows and columns, in print twips.
|
||||
sheet: Option<crate::sheet::Geometry>,
|
||||
/// The farthest point a jump needed; Calc grows to it.
|
||||
reach: (i32, i32),
|
||||
pages: Vec<Rect>,
|
||||
@@ -210,6 +213,7 @@ impl LokView {
|
||||
origin: Point::default(),
|
||||
spare: (0.0, 0.0),
|
||||
frozen: (0, 0),
|
||||
sheet: None,
|
||||
reach: (0, 0),
|
||||
pages,
|
||||
focus: cx.focus_handle().tab_stop(true),
|
||||
|
||||
@@ -60,8 +60,8 @@ pub(super) enum Input {
|
||||
from: (i32, i32),
|
||||
to: (i32, i32),
|
||||
},
|
||||
/// The area the view shows, in twips.
|
||||
Visible(Rect),
|
||||
/// The area shown in twips, and the tile scale.
|
||||
Visible(Rect, (u32, i32)),
|
||||
/// Shows sheet or slide `part`, from 0.
|
||||
Part(usize),
|
||||
}
|
||||
@@ -74,7 +74,7 @@ impl Input {
|
||||
Input::Key { key_code, .. } => !matches!(key_code & 0x0FFF, 1024..=1031 | 1281),
|
||||
Input::Mouse(_)
|
||||
| Input::Copy { cut: false }
|
||||
| Input::Visible(_)
|
||||
| Input::Visible(..)
|
||||
| Input::Part(_)
|
||||
| Input::Theme(_) => false,
|
||||
Input::Run { commands, .. } => commands.iter().any(|(id, _)| *id != "edit.select_all"),
|
||||
@@ -171,7 +171,7 @@ fn lok_button(button: MouseButton) -> Option<i32> {
|
||||
/// Runs one input; gives a copy's mark and the revision.
|
||||
pub(super) fn run(worker: &Mutex<Worker>, doc: &Doc, input: Input) -> (io::Result<Option<String>>, Option<u64>) {
|
||||
let mut worker = worker.lock().expect("the worker lock");
|
||||
let counts = !matches!(input, Input::Visible(_));
|
||||
let counts = !matches!(input, Input::Visible(..));
|
||||
let copied = apply(&mut worker, doc, input);
|
||||
// A failed input may have moved the revision too.
|
||||
let now = match counts {
|
||||
@@ -189,7 +189,7 @@ fn apply(worker: &mut Worker, doc: &Doc, input: Input) -> io::Result<Option<Stri
|
||||
} => worker.post_key(doc, char_code, key_code),
|
||||
Input::Mouse(event) => worker.post_mouse(doc, event),
|
||||
Input::Drag { from, to } => worker.drag_graphic(doc, from, to),
|
||||
Input::Visible(area) => doc.visible_area(worker, area),
|
||||
Input::Visible(area, scale) => doc.visible_area(worker, area, scale),
|
||||
Input::Part(part) => doc.show_sheet(worker, part),
|
||||
Input::Complete(name) => doc.complete_function(worker, &name),
|
||||
Input::Theme(scheme) => worker.run(doc, "view.theme", &[scheme]),
|
||||
@@ -280,7 +280,8 @@ impl LokView {
|
||||
count: usize,
|
||||
modifiers: &Modifiers,
|
||||
) {
|
||||
let (x, y) = self.doc_point(position);
|
||||
// The kernel reads clicks in tile twips.
|
||||
let (x, y) = self.tile_point(position);
|
||||
self.send(Input::Mouse(Mouse {
|
||||
kind,
|
||||
x,
|
||||
|
||||
@@ -272,7 +272,7 @@ impl LokView {
|
||||
},
|
||||
);
|
||||
let pages = if self.pages.is_empty() {
|
||||
vec![self.screen_rect((0, 0, extent.0, extent.1))]
|
||||
vec![self.tile_screen_rect((0, 0, extent.0, extent.1))]
|
||||
} else {
|
||||
self.pages
|
||||
.iter()
|
||||
@@ -283,10 +283,11 @@ impl LokView {
|
||||
geom.twips_of(bounds.size.width.into()),
|
||||
geom.twips_of(bounds.size.height.into()),
|
||||
);
|
||||
if self.shown != Some((sx, sy, vw, vh)) {
|
||||
self.shown = Some((sx, sy, vw, vh));
|
||||
let scale = (geom.tile_pixels(), TILE_TWIPS);
|
||||
if self.shown != Some(((sx, sy, vw, vh), scale)) {
|
||||
self.shown = Some(((sx, sy, vw, vh), scale));
|
||||
self.failed.clear();
|
||||
self.send(input::Input::Visible((sx, sy, vw, vh)));
|
||||
self.send(input::Input::Visible((sx, sy, vw, vh), scale));
|
||||
}
|
||||
let (ax, ay) = self.axes();
|
||||
let side = px(geom.px_of(TILE_TWIPS));
|
||||
|
||||
@@ -41,9 +41,10 @@ impl LokView {
|
||||
self.scroll_by(dx, dy, cx);
|
||||
}
|
||||
|
||||
/// Scrolls `rect` into view; frozen parts always show.
|
||||
pub fn show(&mut self, (x, y, w, h): Rect, cx: &mut Context<Self>) {
|
||||
let (fx, fy) = self.frozen;
|
||||
/// Scrolls print-twips `rect` into view; frozen parts always show.
|
||||
pub fn show(&mut self, rect: Rect, cx: &mut Context<Self>) {
|
||||
let (x, y, w, h) = self.tile_rect(rect);
|
||||
let (fx, fy) = self.frozen_tiles();
|
||||
let (vw, vh) = (
|
||||
self.geom.twips_of(self.viewport.0) - fx,
|
||||
self.geom.twips_of(self.viewport.1) - fy,
|
||||
@@ -63,7 +64,7 @@ impl LokView {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Freezes what lies before `frozen`, in twips.
|
||||
/// Freezes what lies before `frozen`, in print twips.
|
||||
pub fn set_frozen(&mut self, frozen: (i32, i32), cx: &mut Context<Self>) {
|
||||
if self.frozen != frozen {
|
||||
log::info!("lok: frozen at {frozen:?}");
|
||||
@@ -75,7 +76,8 @@ impl LokView {
|
||||
/// Scrolls `rect` into view and puts the cursor there.
|
||||
pub fn reveal(&mut self, rect: Rect, cx: &mut Context<Self>) {
|
||||
self.show(rect, cx);
|
||||
let (x, y, _, h) = rect;
|
||||
// Clicks land in tile twips.
|
||||
let (x, y, _, h) = self.tile_rect(rect);
|
||||
log::info!("lok: reveal at {x},{y}");
|
||||
for kind in [0, 1] {
|
||||
let (count, buttons, modifiers) = (1, 1, 0);
|
||||
@@ -108,8 +110,13 @@ impl LokView {
|
||||
)
|
||||
}
|
||||
|
||||
/// The document point under a view position (LOK-04).
|
||||
/// The print-twips document point under a view position (LOK-04).
|
||||
pub fn doc_point(&self, position: Point<Pixels>) -> (i32, i32) {
|
||||
self.print_of(self.tile_point(position))
|
||||
}
|
||||
|
||||
/// The tile-twips point under a view position.
|
||||
pub(super) fn tile_point(&self, position: Point<Pixels>) -> (i32, i32) {
|
||||
let local = position - self.origin;
|
||||
let (ax, ay) = self.axes();
|
||||
(
|
||||
@@ -121,14 +128,17 @@ impl LokView {
|
||||
/// The panes of each axis.
|
||||
pub(super) fn axes(&self) -> (super::panes::Axis, super::panes::Axis) {
|
||||
let axis = |frozen, scroll| super::panes::Axis { frozen, scroll };
|
||||
(
|
||||
axis(self.frozen.0, self.scroll.0),
|
||||
axis(self.frozen.1, self.scroll.1),
|
||||
)
|
||||
let (fx, fy) = self.frozen_tiles();
|
||||
(axis(fx, self.scroll.0), axis(fy, self.scroll.1))
|
||||
}
|
||||
|
||||
/// The window point of a document point in twips (LOK-04).
|
||||
pub fn window_point(&self, (x, y): (i32, i32)) -> gpui::Point<Pixels> {
|
||||
/// The window point of a print-twips document point (LOK-04).
|
||||
pub fn window_point(&self, at: (i32, i32)) -> gpui::Point<Pixels> {
|
||||
self.tile_window_point(self.tile_of(at))
|
||||
}
|
||||
|
||||
/// The window point of a tile-twips point.
|
||||
pub(super) fn tile_window_point(&self, (x, y): (i32, i32)) -> gpui::Point<Pixels> {
|
||||
let (ax, ay) = self.axes();
|
||||
let (x, y) = (self.geom.px_of(ax.show(x)), self.geom.px_of(ay.show(y)));
|
||||
self.origin + point(px(self.spare.0 + x), px(self.spare.1 + y))
|
||||
@@ -139,12 +149,19 @@ impl LokView {
|
||||
Bounds::from_corners(self.window_point((x, y)), self.window_point((x + w, y + h)))
|
||||
}
|
||||
|
||||
/// A tile-twips rect in window pixels.
|
||||
pub(super) fn tile_screen_rect(&self, (x, y, w, h): crate::Rect) -> Bounds<Pixels> {
|
||||
Bounds::from_corners(self.tile_window_point((x, y)), self.tile_window_point((x + w, y + h)))
|
||||
}
|
||||
|
||||
/// The cursor rect in window pixels.
|
||||
pub fn cursor_bounds(&self) -> Option<Bounds<Pixels>> {
|
||||
let (x, y, w, h) = self.cursor?;
|
||||
let origin = self.window_point((x, y));
|
||||
let end = self.window_point((x + w, y + h));
|
||||
Some(Bounds {
|
||||
origin: self.window_point((x, y)),
|
||||
size: size(px(self.geom.px_of(w.max(1))), px(self.geom.px_of(h))),
|
||||
origin,
|
||||
size: size((end.x - origin.x).max(px(self.geom.px_of(1))), end.y - origin.y),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//! Calc reports print twips; tiles and clicks take tile twips.
|
||||
|
||||
use gpui::Context;
|
||||
|
||||
use super::{LokView, TILE_TWIPS};
|
||||
use crate::{Rect, sheet::Geometry};
|
||||
|
||||
impl LokView {
|
||||
/// Lays the sheet out the kernel's way.
|
||||
pub fn set_geometry(&mut self, geometry: Geometry, cx: &mut Context<Self>) {
|
||||
if self.sheet.as_ref() != Some(&geometry) {
|
||||
self.sheet = Some(geometry);
|
||||
self.clamp_scroll();
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/// Device pixels per twip, as the kernel paints our tiles.
|
||||
fn ppt(&self) -> f64 {
|
||||
f64::from(self.geom.tile_pixels()) / f64::from(TILE_TWIPS)
|
||||
}
|
||||
|
||||
/// A print-twips point in tile twips.
|
||||
pub(super) fn tile_of(&self, (x, y): (i32, i32)) -> (i32, i32) {
|
||||
match &self.sheet {
|
||||
Some(sheet) => (sheet.columns.tile(x, self.ppt()), sheet.rows.tile(y, self.ppt())),
|
||||
None => (x, y),
|
||||
}
|
||||
}
|
||||
|
||||
/// A tile-twips point in print twips.
|
||||
pub(super) fn print_of(&self, (x, y): (i32, i32)) -> (i32, i32) {
|
||||
match &self.sheet {
|
||||
Some(sheet) => (sheet.columns.print(x, self.ppt()), sheet.rows.print(y, self.ppt())),
|
||||
None => (x, y),
|
||||
}
|
||||
}
|
||||
|
||||
/// A print-twips rect in tile twips.
|
||||
pub(super) fn tile_rect(&self, (x, y, w, h): Rect) -> Rect {
|
||||
let (left, top) = self.tile_of((x, y));
|
||||
let (right, bottom) = self.tile_of((x + w, y + h));
|
||||
(left, top, right - left, bottom - top)
|
||||
}
|
||||
|
||||
/// The frozen extent in tile twips.
|
||||
pub(super) fn frozen_tiles(&self) -> (i32, i32) {
|
||||
self.tile_of(self.frozen)
|
||||
}
|
||||
|
||||
/// Where the scrolling pane starts, in print twips.
|
||||
pub fn scrolled_start(&self) -> (i32, i32) {
|
||||
let (fx, fy) = self.frozen_tiles();
|
||||
self.print_of((fx + self.scroll.0, fy + self.scroll.1))
|
||||
}
|
||||
}
|
||||
@@ -60,3 +60,58 @@ fn a_tall_sheet_paints_and_keeps_only_tiles_near_the_screen() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// 6000 rows of 0.5 cm; tiles round each to pixels.
|
||||
const SHORT_ROWS: &str = r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
|
||||
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
|
||||
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
|
||||
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
|
||||
<office:automatic-styles><style:style style:name="ro1" style:family="table-row"><style:table-row-properties style:row-height="0.5cm" style:use-optimal-row-height="false"/></style:style></office:automatic-styles>
|
||||
<office:body><office:spreadsheet><table:table table:name="S">
|
||||
<table:table-row table:style-name="ro1" table:number-rows-repeated="6000"><table:table-cell table:number-columns-repeated="4"/></table:table-row>
|
||||
</table:table></office:spreadsheet></office:body>
|
||||
</office:document>"#;
|
||||
|
||||
#[test]
|
||||
fn a_click_far_down_a_sheet_selects_the_cell_under_it() {
|
||||
let Some(install) = crate::client::tests::install() else {
|
||||
eprintln!("SKIP: no pinned LOK build");
|
||||
return;
|
||||
};
|
||||
let mut cx = gpui::TestAppContext::single();
|
||||
let (view, worker) = cx.update(|app| live_view_of(app, &install, "short.fods", SHORT_ROWS));
|
||||
let json = cx.update(|app| {
|
||||
let read = view.read(app);
|
||||
worker.lock().expect("the worker lock").values(&read.doc, crate::sheet::GEOMETRY).expect("geometry")
|
||||
});
|
||||
let geometry = crate::sheet::geometry(&json).expect("parsed");
|
||||
let (row, column) = (4997, 1);
|
||||
let cell = (
|
||||
geometry.columns.start(column),
|
||||
geometry.rows.start(row),
|
||||
geometry.columns.size(column),
|
||||
geometry.rows.size(row),
|
||||
);
|
||||
cx.update(|app| {
|
||||
view.update(app, |view, cx| {
|
||||
view.geom.dpi = 2.0;
|
||||
view.set_geometry(geometry.clone(), cx);
|
||||
view.prepare(Bounds { origin: point(px(0.0), px(0.0)), size: size(px(800.0), px(600.0)) });
|
||||
view.show(cell, cx);
|
||||
let at = view.window_point((cell.0 + cell.2 / 2, cell.1 + cell.3 / 2));
|
||||
for kind in [0, 1] {
|
||||
view.mouse(kind, at, 1, 1, &gpui::Modifiers::default());
|
||||
}
|
||||
})
|
||||
});
|
||||
let mut address = String::new();
|
||||
for _ in 0..200 {
|
||||
cx.executor().tick();
|
||||
address = cx.update(|app| view.read(app).cell().address.clone());
|
||||
if address == "B4998" {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert_eq!(address, "B4998");
|
||||
}
|
||||
@@ -246,9 +246,15 @@ fn answer(lok: &Lok, tag: u8, id: u64, payload: &[u8]) {
|
||||
.u64()
|
||||
.and_then(|id| {
|
||||
let mut number = || i32::try_from(unpack.i64()?).map_err(io::Error::other);
|
||||
Ok((id, (number()?, number()?, number()?, number()?)))
|
||||
Ok((id, (number()?, number()?, number()?, number()?), (number()?, number()?)))
|
||||
})
|
||||
.and_then(|(id, (x, y, w, h), (pixels, twips))| {
|
||||
// Calc reads clicks at this scale, not the last tile's.
|
||||
with_doc(id, |doc| {
|
||||
doc.set_client_zoom(pixels, twips);
|
||||
doc.set_visible_area(x, y, w, h)
|
||||
})
|
||||
})
|
||||
.and_then(|(id, (x, y, w, h))| with_doc(id, |doc| doc.set_visible_area(x, y, w, h)))
|
||||
.map(|()| Vec::new()),
|
||||
tag::SELECTION_TEXT => unpack
|
||||
.u64()
|
||||
|
||||
Reference in new issue
Block a user