Merge pull request #246 from theironchef/fix/type-drag-select
Type tool: a drag across text that isn't being edited selects it
This commit is contained in:
commit
cc4992172a
|
|
@ -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);
|
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.
|
// Click into existing text: place the caret.
|
||||||
if let Some(h) = hit_test(cx.doc, start, cx.hit_options())
|
if let Some(out) = self.edit_at(cx, start) {
|
||||||
&& 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]})));
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
let mut out = self.finish(cx);
|
||||||
let drag = self.drag.take();
|
let drag = self.drag.take();
|
||||||
// Area Type / Type on a Path: click a path.
|
// Area Type / Type on a Path: click a path.
|
||||||
if self.mode != Mode::Type && drag.is_none() {
|
if self.mode != Mode::Type && drag.is_none() {
|
||||||
|
|
@ -357,6 +364,12 @@ impl Tool for TypeTool {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
self.clicks = (None, 0);
|
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.press = Some(ev.pos);
|
||||||
self.drag = None;
|
self.drag = None;
|
||||||
vec![]
|
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)));
|
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]
|
#[test]
|
||||||
fn select_all_and_styled_paste() {
|
fn select_all_and_styled_paste() {
|
||||||
let (d, _, mut tool) = editing("abc");
|
let (d, _, mut tool) = editing("abc");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue