Merge pull request #284 from theironchef/fix/double-click-type-caret
Canvas: double-clicking type with a selection tool puts the caret there
This commit is contained in:
commit
6a62dc58ba
|
|
@ -110,6 +110,7 @@ grade by behaviour against `plan/illustrator/`, not by whether a menu item exist
|
|||
- **Live Corners:** drag a live rectangle's corner widgets (Selection or Direct Selection) to round all corners, with a radius readout.
|
||||
- **Graphs:** Column, Stacked Column, Bar, Stacked Bar, Line, Area, Scatter, Pie and Radar graph tools with Graph Data and Graph Type.
|
||||
- **Other:** Eyedropper, Gradient annotator, Artboard, Measure, Type, Hand, Zoom, Rotate View.
|
||||
- **Editing type:** double-clicking type with a selection tool switches to the Type tool with the caret where it was clicked.
|
||||
- **Temporary tools:** Cmd with any other tool drags with the selection tool used last (Selection, Direct Selection or Group Selection). Held Space pans and Cmd+Space zooms (Cmd+Alt+Space out) whatever the tool.
|
||||
- **Tool double-clicks:** double-clicking a tool's button opens its options: Hand fits the artboard in the window, Zoom shows 100 %, Rotate, Scale, Reflect and Shear open their Object › Transform dialogs, Gradient, Eyedropper, Blend and the Liquify tools their panels or options.
|
||||
- **Drawing aids:** Smart Guides and snapping, guides dragged out of the rulers, and Draw Normal / Behind / Inside modes.
|
||||
|
|
|
|||
|
|
@ -576,7 +576,15 @@ fn handle_input(app: &mut VectorcraftApp, ui: &Ui, resp: &egui::Response, rect:
|
|||
&& let Some(p) = hover
|
||||
{
|
||||
let ev = PointerEvent { kind: PointerKind::DoubleClick, pos: xf.to_doc(p), mods: mods(m, space), pressure: 1.0 };
|
||||
let before = app.session.tool_id().to_string();
|
||||
dispatch(app, &ev, view);
|
||||
// A double-click on type switched a selection tool to the Type tool: the caret goes where
|
||||
// the type was clicked, so typing edits it at once.
|
||||
if before != "type" && app.session.tool_id() == "type" {
|
||||
for kind in [PointerKind::Down, PointerKind::Up] {
|
||||
dispatch(app, &PointerEvent { kind, ..ev }, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
if drag.is_some() || pointer.is_moving() {
|
||||
ui.ctx().request_repaint();
|
||||
|
|
@ -1638,6 +1646,45 @@ mod tests {
|
|||
assert!((after.center.x - (before.center.x - 30.0 / before.zoom)).abs() < 1e-6, "{before:?} → {after:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_clicking_type_with_the_selection_tool_puts_the_caret_there() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
|
||||
let id = app.session.execute("text.create", &json!({"x": 100, "y": 150, "text": "Hello world", "size": 24})).unwrap()["id"].as_u64().unwrap();
|
||||
app.session.execute("select.none", &json!({})).unwrap();
|
||||
app.select_tool("selection");
|
||||
let ctx = egui::Context::default();
|
||||
let timed = |app: &mut VectorcraftApp, time: f64, events: Vec<egui::Event>| {
|
||||
let screen = egui::Rect::from_min_size(Pos2::ZERO, vec2(800.0, 600.0));
|
||||
let mut out =
|
||||
ctx.run_ui(egui::RawInput { screen_rect: Some(screen), time: Some(time), events, ..Default::default() }, |ui| show(app, ui));
|
||||
out.textures_delta.clear();
|
||||
};
|
||||
timed(&mut app, 0.0, vec![]);
|
||||
let xf = Xf::new(app.canvas_rect.unwrap(), app.view().unwrap());
|
||||
let text = |app: &VectorcraftApp| match &app.session.active().unwrap().doc.node(vectorcraft_doc::NodeId(id)).unwrap().kind {
|
||||
NodeKind::Text(t) => t.plain_text(),
|
||||
_ => panic!("not text"),
|
||||
};
|
||||
// Double-click the middle of the text.
|
||||
let b = app.session.active().unwrap().doc.node(vectorcraft_doc::NodeId(id)).unwrap().geometric_bounds().unwrap();
|
||||
let at = xf.to_screen(b.center());
|
||||
let button = |pressed| egui::Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() };
|
||||
timed(&mut app, 1.0, vec![egui::Event::PointerMoved(at), button(true), button(false), button(true), button(false)]);
|
||||
timed(&mut app, 1.1, vec![]);
|
||||
// The Type tool edits the text, with the caret inside it, where it was clicked: typing goes
|
||||
// into the text, not to tool shortcuts (X would swap fill and stroke).
|
||||
assert_eq!(app.session.tool_id(), "type");
|
||||
assert!(app.session.tool_wants_text());
|
||||
let o = app.session.tool_options();
|
||||
assert_eq!(o["editing"], json!(id));
|
||||
let caret = o["caret"].as_u64().unwrap();
|
||||
assert!((1..11).contains(&caret), "caret {caret}");
|
||||
app.session.tool_text("X", app.view_info()).unwrap();
|
||||
let t = text(&app);
|
||||
assert_eq!((t.len(), t.find('X')), (12, Some(caret as usize)), "{t}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn middle_drag_pans_the_view_with_any_tool() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
|
|
|
|||
Loading…
Reference in New Issue