mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-28 18:22:06 +01:00
Type: keep text selection highlight visible while Command/Ctrl is held (#5542)
* Type: keep text selection highlight visible while Command/Ctrl is held * Type: match Photoshop 1px dark frame and handle styling for type transform * Merge main; keep the transform box and underline colours from the theme tokens The selection-highlight fix stands on its own; the hard-coded box and underline colours and the removed reference point were unrelated to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: safvanedge <241307593+safvanedge@users.noreply.github.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
safvanedge
Brandon Thomas
Claude Opus 5.5
parent
7efebfa050
commit
fd28da56da
@@ -1014,20 +1014,20 @@ pub fn draw_overlay(app: &mut PhotocraftApp, painter: &egui::Painter, xf: &ViewX
|
||||
}
|
||||
// Frame: paragraph text shows its box with handles; point text an underline per line.
|
||||
let mods = crate::workspace_ui::sticky_mods(app, painter.ctx().input(|i| i.modifiers));
|
||||
if crate::type_transform::draw(app, painter, xf, mods) {
|
||||
return;
|
||||
}
|
||||
let has_transform = crate::type_transform::draw(app, painter, xf, mods);
|
||||
let shape = app.session.active().and_then(|s| text_layer(&s.doc, id).map(|t| t.shape.clone()));
|
||||
let frame = Stroke::new(1.0, t.accent);
|
||||
match shape {
|
||||
Some(photocraft_doc::text::TextShape::Box { x, y, width, height }) => {
|
||||
let c = [scr_t(x, y), scr_t(x + width, y), scr_t(x + width, y + height), scr_t(x, y + height)];
|
||||
painter.add(egui::Shape::closed_line(c.to_vec(), frame));
|
||||
let mids = [c[0].lerp(c[1], 0.5), c[1].lerp(c[2], 0.5), c[2].lerp(c[3], 0.5), c[3].lerp(c[0], 0.5)];
|
||||
for p in c.iter().chain(mids.iter()) {
|
||||
let r = egui::Rect::from_center_size(*p, egui::vec2(7.0, 7.0));
|
||||
painter.rect_filled(r, 0.0, Color32::WHITE);
|
||||
painter.rect_stroke(r, 0.0, frame, egui::StrokeKind::Inside);
|
||||
if !has_transform {
|
||||
let c = [scr_t(x, y), scr_t(x + width, y), scr_t(x + width, y + height), scr_t(x, y + height)];
|
||||
painter.add(egui::Shape::closed_line(c.to_vec(), frame));
|
||||
let mids = [c[0].lerp(c[1], 0.5), c[1].lerp(c[2], 0.5), c[2].lerp(c[3], 0.5), c[3].lerp(c[0], 0.5)];
|
||||
for p in c.iter().chain(mids.iter()) {
|
||||
let r = egui::Rect::from_center_size(*p, egui::vec2(7.0, 7.0));
|
||||
painter.rect_filled(r, 0.0, Color32::WHITE);
|
||||
painter.rect_stroke(r, 0.0, frame, egui::StrokeKind::Inside);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
||||
@@ -779,6 +779,23 @@ fn temporary_type_transform_visibility_and_cursors() {
|
||||
assert!(crate::type_transform::visible(h.state(), sticky));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_selection_highlight_visible_with_command_held() {
|
||||
let (app, _id) = transform_app(false, false, Affine::IDENTITY);
|
||||
let mut h = harness(1.0, app);
|
||||
if let Some(ed) = h.state_mut().ui.text_edit.as_mut() {
|
||||
ed.anchor = 0;
|
||||
ed.caret = 5;
|
||||
}
|
||||
hold(&mut h, type_command());
|
||||
h.run();
|
||||
let accent = crate::theme::Tokens::get(&h.ctx).accent;
|
||||
let expected_fill = egui::Color32::from_rgba_unmultiplied(accent.r(), accent.g(), accent.b(), 110);
|
||||
let has_selection_highlight =
|
||||
h.output().shapes.iter().any(|clipped| if let egui::Shape::Path(path) = &clipped.shape { path.fill == expected_fill && path.closed } else { false });
|
||||
assert!(has_selection_highlight, "selection highlight must remain visible while Ctrl/Cmd is held");
|
||||
}
|
||||
|
||||
/// Real canvas input: layer-local scaling stays correct across orientation, zoom, HiDPI and flip.
|
||||
#[test]
|
||||
fn temporary_type_transform_scales_without_reflow_or_leaving_type() {
|
||||
|
||||
Reference in New Issue
Block a user