mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-30 12:57:28 -06:00
Type: a click inside the paragraph box off the glyphs moves the caret (#7606)
While editing paragraph text, a click inside the box that missed the glyphs (left of a line's start, or below the last line) committed the edit. Like Photoshop, it now places the caret at the nearest position; a click outside the box still commits. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
fe64e5a2bd
commit
c78ec47f4b
@@ -237,6 +237,15 @@ fn resize_box(app: &mut PhotocraftApp, ed: &TextEdit, i: u8, x: f64, y: f64) {
|
||||
let _ = app.run("type.edit", json!({"layer": ed.layer, "box": [o.x, o.y, x1 - x0, y1 - y0], "coalesce": ed.session}));
|
||||
}
|
||||
|
||||
/// True when document point (`x`, `y`) lies inside the paragraph box of type layer `id` (false
|
||||
/// for point text).
|
||||
fn inside_box(app: &mut PhotocraftApp, id: LayerId, x: f64, y: f64) -> bool {
|
||||
let Some((bx, by, w, h)) = box_shape(app, id) else { return false };
|
||||
let Some((_, aff, _)) = layout(app, id) else { return false };
|
||||
let (tx, ty) = to_text(&aff, x, y);
|
||||
tx >= bx && tx <= bx + w && ty >= by && ty <= by + h
|
||||
}
|
||||
|
||||
/// Pointer down with the Type tool. Returns true when the press was consumed (no box drag).
|
||||
pub fn pointer_down(app: &mut PhotocraftApp, x: f64, y: f64, mods: egui::Modifiers) -> bool {
|
||||
if let Some(ed) = app.ui.text_edit.clone() {
|
||||
@@ -247,7 +256,9 @@ pub fn pointer_down(app: &mut PhotocraftApp, x: f64, y: f64, mods: egui::Modifie
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if hit_layer(app, x, y) == Some(id) {
|
||||
// Photoshop: anywhere inside the paragraph box places the caret, even off the glyphs
|
||||
// (left of a line's start, below the last line); only a click outside it commits.
|
||||
if hit_layer(app, x, y) == Some(id) || inside_box(app, id, x, y) {
|
||||
let off = hit_offset(app, id, x, y);
|
||||
if let Some(e) = app.ui.text_edit.as_mut() {
|
||||
e.caret = off;
|
||||
|
||||
@@ -964,6 +964,33 @@ fn temporary_type_transform_free_scale_center_scale_move_skew_and_rotation() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Editing paragraph text, a click inside the box but off the glyphs moves the caret to the
|
||||
/// nearest offset, as in Photoshop; a click outside the box still commits.
|
||||
#[test]
|
||||
fn click_inside_the_paragraph_box_off_the_glyphs_moves_the_caret() {
|
||||
use crate::canvas::{ToolEvent, tool_event};
|
||||
// The box is 240 × 180; the two 32 pt lines only fill its top.
|
||||
let (mut app, id) = transform_app(true, false, Affine::translate(400.0, 350.0));
|
||||
let (bx, by, _, h) = super::box_shape(&app, id).unwrap();
|
||||
let (l, aff, _) = layout(&mut app, id).unwrap();
|
||||
let click = |app: &mut PhotocraftApp, tx: f32, ty: f32| {
|
||||
let p = aff.apply(Point::new(f64::from(tx), f64::from(ty)));
|
||||
tool_event(app, ToolEvent::Down { x: p.x, y: p.y, pressure: 1.0 }, Modifiers::NONE);
|
||||
tool_event(app, ToolEvent::Up { x: p.x, y: p.y }, Modifiers::NONE);
|
||||
};
|
||||
let layers = app.session.active().unwrap().doc.layers.len();
|
||||
// Near the bottom of the box, just right of its left edge.
|
||||
assert!(!photocraft_text::text_point_inside(&l, bx + 8.0, by + h - 8.0, 6.0), "the point is off the glyphs");
|
||||
click(&mut app, bx + 8.0, by + h - 8.0);
|
||||
let ed = app.ui.text_edit.clone().expect("still editing");
|
||||
// "Hello é世界\n" is 10 characters: the start of the second line.
|
||||
assert_eq!((ed.layer, ed.caret, ed.anchor), (id.0, 10, 10));
|
||||
// Outside the box the edit commits, without starting new text.
|
||||
click(&mut app, bx - 40.0, by + h - 8.0);
|
||||
assert!(app.ui.text_edit.is_none());
|
||||
assert_eq!(app.session.active().unwrap().doc.layers.len(), layers);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn temporary_type_transform_noop_cancel_and_stale_capture() {
|
||||
use crate::canvas::{ToolEvent, tool_event};
|
||||
|
||||
Reference in New Issue
Block a user