use pdfrum_doc::vt::{Config, Metrics};
use pdfrum_form::edit::ops::{self, TextEdit, insert_char, replace_selection};
fn helvetica(ch: u32) -> i32 {
match char::from_u32(ch) {
Some('A' | 'B' | 'E') => 667,
Some('C' | 'D' | 'H') => 722,
Some('F') => 611,
Some('G') => 778,
Some(' ') => 278,
_ => 556,
}
}
fn metrics() -> Metrics<'static> {
Metrics {
width: &helvetica,
ascent: 723,
descent: -207,
}
}
fn config() -> Config {
Config {
plate: kurbo::Rect::new(101.0, 101.0, 199.0, 129.0),
font_size: 12.0,
..Config::default()
}
}
fn field(text: &str) -> TextEdit {
TextEdit::new(text, &config(), &metrics(), true)
}
const CLICK: (f64, f64) = (134.0, 115.0);
#[test]
fn a_click_at_the_fixtures_x_lands_after_four_characters() {
let (config, metrics) = (config(), metrics());
let mut edit = field("");
for ch in "ABCDEFGH".chars() {
insert_char(&mut edit, &config, &metrics, ch, None);
}
assert_eq!(edit.text, "ABCDEFGH");
ops::click_at(
&mut edit,
&config,
&metrics,
kurbo::Point::new(CLICK.0, CLICK.1),
);
assert_eq!(
edit.caret_index(),
4,
"the click must land after ABCD; a missing vertical offset answers 8"
);
replace_selection(&mut edit, &config, &metrics, "Hello", None);
assert_eq!(edit.text, "ABCDHelloEFGH");
}
#[test]
fn the_field_carries_a_nonzero_drawing_offset() {
let edit = field("ABCDEFGH");
assert!(
edit.offset.1 != 0.0,
"a centred single-line field draws below its layout"
);
let multiline = TextEdit::new("ABCDEFGH", &config(), &metrics(), false);
assert_eq!(multiline.offset, (0.0, 0.0));
}
#[test]
fn clicks_at_the_fields_ends_reach_both_ends_of_the_text() {
let (config, metrics) = (config(), metrics());
let mut edit = field("ABCDEFGH");
ops::click_at(
&mut edit,
&config,
&metrics,
kurbo::Point::new(102.0, 115.0),
);
assert_eq!(edit.caret_index(), 0);
ops::click_at(
&mut edit,
&config,
&metrics,
kurbo::Point::new(195.0, 115.0),
);
assert_eq!(edit.caret_index(), 8);
}
#[test]
fn a_drag_selects_between_two_points() {
let (config, metrics) = (config(), metrics());
let mut edit = field("ABCDEFGH");
ops::click_at(
&mut edit,
&config,
&metrics,
kurbo::Point::new(102.0, 115.0),
);
ops::drag_to(
&mut edit,
&config,
&metrics,
kurbo::Point::new(CLICK.0, CLICK.1),
);
assert_eq!(edit.selected_text(), "ABCD");
}
#[test]
fn a_double_click_selects_the_whole_field() {
let (config, metrics) = (config(), metrics());
let mut edit = TextEdit::new("Hello World", &config, &metrics, true);
edit.select_all();
assert_eq!(
edit.selected_text(),
"Hello World",
"the whole field, not the word under the pointer"
);
}
#[test]
fn a_double_click_on_a_multiline_field_takes_every_line() {
let mut config = config();
config.multi_line = true;
config.auto_return = true;
let metrics = metrics();
let mut edit = TextEdit::new("one\ntwo\nthree", &config, &metrics, true);
let middle = kurbo::Point::new(CLICK.0, CLICK.1);
let line_only = {
let mut probe = edit.clone();
ops::select_line_at(&mut probe, &config, &metrics, middle);
probe.selected_text()
};
edit.select_all();
assert_eq!(edit.selected_text(), "one\ntwo\nthree");
assert_ne!(
edit.selected_text(),
line_only,
"the two readings must actually differ here, or this pins nothing"
);
}
#[test]
fn the_overlay_shows_a_caret_or_bands_but_never_both() {
let (config, metrics) = (config(), metrics());
let mut edit = field("ABCDEFGH");
ops::click_at(
&mut edit,
&config,
&metrics,
kurbo::Point::new(CLICK.0, CLICK.1),
);
let caret_only = ops::highlight(&edit, &config, &metrics, 0.4);
assert!(caret_only.caret.is_some());
assert!(caret_only.selection.is_empty());
edit.select_all();
let bands_only = ops::highlight(&edit, &config, &metrics, 0.4);
assert!(
bands_only.caret.is_none(),
"a field with a selection shows no caret"
);
assert!(!bands_only.selection.is_empty());
}