Type tool: a drag across text that isn't being edited selects it
A press only started a selection inside the text being edited; on other type it waited for the release, which placed the caret at the press and ignored the drag, so the first drag across a word never selected it. A press on type now starts editing it there (the same code a click used on release), so the drag selects at once; a plain click still just places the caret. Fixes #245. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
83faf568b0
commit
c60cb4a9c2
|
|
@ -235,19 +235,26 @@ impl TypeTool {
|
|||
}
|
||||
}
|
||||
|
||||
fn on_up(&mut self, cx: &ToolContext, start: Point) -> Vec<Action> {
|
||||
/// Start editing the type under `p` with the caret there → the actions (ending the previous
|
||||
/// edit, selecting the type); None when no type is under `p`.
|
||||
fn edit_at(&mut self, cx: &ToolContext, p: Point) -> Option<Vec<Action>> {
|
||||
let h = hit_test(cx.doc, p, cx.hit_options())?;
|
||||
let Some(NodeKind::Text(t)) = cx.doc.node(h.leaf).map(|n| &n.kind) else { return None };
|
||||
let lay = self.layout(t);
|
||||
let byte = vectorcraft_text::hit_byte(&lay, t.xf.inverse() * p);
|
||||
let mut out = self.finish(cx);
|
||||
self.start_editing(h.leaf, byte);
|
||||
self.clicks = (Some(p), 1);
|
||||
out.push(Action::Exec("select.set".into(), json!({"ids": [h.leaf.0]})));
|
||||
Some(out)
|
||||
}
|
||||
|
||||
fn on_up(&mut self, cx: &ToolContext, start: Point) -> Vec<Action> {
|
||||
// Click into existing text: place the caret.
|
||||
if let Some(h) = hit_test(cx.doc, start, cx.hit_options())
|
||||
&& let Some(NodeKind::Text(t)) = cx.doc.node(h.leaf).map(|n| &n.kind)
|
||||
{
|
||||
let lay = self.layout(t);
|
||||
let byte = vectorcraft_text::hit_byte(&lay, t.xf.inverse() * start);
|
||||
self.start_editing(h.leaf, byte);
|
||||
self.clicks = (Some(start), 1);
|
||||
out.push(Action::Exec("select.set".into(), json!({"ids": [h.leaf.0]})));
|
||||
if let Some(out) = self.edit_at(cx, start) {
|
||||
return out;
|
||||
}
|
||||
let mut out = self.finish(cx);
|
||||
let drag = self.drag.take();
|
||||
// Area Type / Type on a Path: click a path.
|
||||
if self.mode != Mode::Type && drag.is_none() {
|
||||
|
|
@ -357,6 +364,12 @@ impl Tool for TypeTool {
|
|||
return out;
|
||||
}
|
||||
self.clicks = (None, 0);
|
||||
// A press on other type edits it from there, so a drag selects its text at once,
|
||||
// as it does in the type being edited.
|
||||
if let Some(out) = self.edit_at(cx, ev.pos) {
|
||||
self.selecting = true;
|
||||
return out;
|
||||
}
|
||||
self.press = Some(ev.pos);
|
||||
self.drag = None;
|
||||
vec![]
|
||||
|
|
|
|||
|
|
@ -176,6 +176,33 @@ fn drag_selects_and_overlay_highlights() {
|
|||
assert_eq!((opts["start"].as_u64(), opts["end"].as_u64()), (Some(7), Some(9)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_drag_across_type_not_being_edited_selects_its_text() {
|
||||
let (d, id) = doc_with_text("Select me please");
|
||||
let mut tool = TypeTool::new("type");
|
||||
let (sel, p) = (Selection::default(), paint());
|
||||
let c = cx(&d, &sel, &p);
|
||||
let t = TypeTool::text(&c, id).unwrap().clone();
|
||||
let lay = vectorcraft_text::layout(FontDb::global(), &t);
|
||||
let pt = |b: usize| {
|
||||
let (a, bb) = vectorcraft_text::caret_position(&lay, b);
|
||||
t.xf * a.midpoint(bb)
|
||||
};
|
||||
let (a, b) = (pt(7), pt(9));
|
||||
// The press starts editing the type and the drag selects, in one gesture.
|
||||
let out = tool.pointer(&c, &PointerEvent::new(PointerKind::Down, a.x + 0.1, a.y));
|
||||
assert!(out.contains(&Action::Exec("select.set".into(), json!({"ids": [id.0]}))));
|
||||
tool.pointer(&c, &PointerEvent::new(PointerKind::Drag, b.x + 0.1, b.y));
|
||||
tool.pointer(&c, &PointerEvent::new(PointerKind::Up, b.x + 0.1, b.y));
|
||||
assert_eq!(tool.editing, Some(id));
|
||||
assert_eq!(tool.sel(), (7, 9));
|
||||
// A plain click still just places the caret.
|
||||
let mut tool = TypeTool::new("type");
|
||||
tool.pointer(&c, &PointerEvent::new(PointerKind::Down, a.x + 0.1, a.y));
|
||||
tool.pointer(&c, &PointerEvent::new(PointerKind::Up, a.x + 0.1, a.y));
|
||||
assert_eq!((tool.editing, tool.sel()), (Some(id), (7, 7)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn select_all_and_styled_paste() {
|
||||
let (d, _, mut tool) = editing("abc");
|
||||
|
|
|
|||
Loading…
Reference in New Issue