Integration: keep a hidden layer's eye box empty (#8496)

The PR widened the eye hit area to the whole column (#8467) but also painted
a 12x12 sunken well in a hidden layer's eye box. The maintainer decided on
#1662 that a hidden layer's eye box stays empty, as in Photoshop (and the
hidden fx-row eye still does), so the well goes; the full-column hit area and
its test stay. New test a_hidden_layers_eye_box_paints_nothing checks, in all
five themes, that nothing is drawn inside a hidden layer's eye column while a
visible layer's eye is; it fails with the well. Also drops the trailing blank
line at EOF of layer_row_ui/tests.rs (cargo fmt).

Co-authored-by: kobaltgit <159009675+kobaltgit@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed 2026-10-22 21:10:34 +02:00
1 parent ffdfa8b3f9
commit 77caa32765
2 files changed
+33 -20

No files matched your search

+32 -3
View File
@@ -653,9 +653,7 @@ fn eye_column_edges_toggle_visibility_without_selecting_layer() {
let visible = |h: &Harness<'_, PhotocraftApp>, id: u64| h.state().session.active().unwrap().doc.layer(photocraft_doc::LayerId(id)).unwrap().visible;
let selected = |h: &Harness<'_, PhotocraftApp>| h.state().session.active().unwrap().active_layer.unwrap().0;
let row_for = |h: &Harness<'_, PhotocraftApp>, id: u64| {
recorded(&h.ctx).into_iter().find(|r| r.layer == id).unwrap().row
};
let row_for = |h: &Harness<'_, PhotocraftApp>, id: u64| recorded(&h.ctx).into_iter().find(|r| r.layer == id).unwrap().row;
let top_row = row_for(&h, l1);
// Click at the far left edge of the eye column (left + 1.0, top + 1.0)
@@ -673,3 +671,34 @@ fn eye_column_edges_toggle_visibility_without_selecting_layer() {
assert_eq!(selected(&h), l0, "click on eye column must not select the layer");
}
/// #1662: a hidden layer's eye box stays empty, as in Photoshop (only a visible layer paints its
/// eye), in every theme; the widened hit area (#8467) changes nothing that is drawn.
#[test]
fn a_hidden_layers_eye_box_paints_nothing() {
fn bounds(shape: &egui::Shape, out: &mut Vec<Rect>) {
match shape {
egui::Shape::Vec(shapes) => shapes.iter().for_each(|s| bounds(s, out)),
s => out.push(s.visual_bounding_rect()),
}
}
for theme in ["promedium", "pro", "studio", "studiolight", "classic"] {
let mut s = photocraft_engine::Session::new();
s.execute("file.new", json!({"width": 64, "height": 48})).unwrap();
let hidden = s.execute("layer.new.layer", json!({"name": "Hidden"})).unwrap()["layer"].as_u64().unwrap();
s.execute("layer.setProps", json!({"layer": hidden, "visible": false})).unwrap();
let shown = s.execute("layer.new.layer", json!({"name": "Shown"})).unwrap()["layer"].as_u64().unwrap();
let h = harness(s, 1.0, theme, 290.0);
let mut drawn = Vec::new();
for clipped in &h.output().shapes {
bounds(&clipped.shape, &mut drawn);
}
let rows = recorded(&h.ctx);
let in_eye_box = |id: u64| {
let row = rows.iter().find(|r| r.layer == id).unwrap().row;
let cell = Rect::from_min_max(row.left_top(), pos2(row.left() + 30.0, row.bottom())).shrink(1.0);
drawn.iter().filter(|b| b.is_positive() && cell.contains_rect(**b)).count()
};
assert!(in_eye_box(shown) > 0, "{theme}: a visible layer paints its eye");
assert_eq!(in_eye_box(hidden), 0, "{theme}: a hidden layer's eye box is left empty");
}
}
+1 -17
View File
@@ -3212,26 +3212,10 @@ fn layer_row(
// The whole eye column takes drags too (so a drag starting on it never reorders the row): dragging down
// the eyes gives every row swept over the visibility the first eye toggled to (#8467).
let eye_resp = ui.interact(eye_cell, ui.id().with(("eye", l.id.0)), Sense::click_and_drag());
// A hidden layer's eye box shows a sunken well indicating its eye socket (#8467).
// A hidden layer's eye box is left empty (still clickable; the whole column takes the click, #8467).
if l.visible {
// Centre the drawing in the column while preserving the visibility hit area.
icons::paint(ui, eye_cell, "eye", 15.0, t.layer_label_icon(l.label));
} else {
let well = Rect::from_center_size(eye_cell.center(), vec2(12.0, 12.0));
if t.bevel {
crate::widgets::surface(ui, well, t.field, false);
} else {
painter.rect_filled(well, t.radius_sm, t.field);
let (hi, lo) = if t.dark() {
(Color32::from_black_alpha(65), Color32::from_white_alpha(35))
} else {
(Color32::from_black_alpha(55), Color32::from_white_alpha(70))
};
painter.line_segment([well.left_bottom(), well.left_top()], Stroke::new(1.0, hi));
painter.line_segment([well.left_top(), well.right_top()], Stroke::new(1.0, hi));
painter.line_segment([well.right_top(), well.right_bottom()], Stroke::new(1.0, lo));
painter.line_segment([well.right_bottom(), well.left_bottom()], Stroke::new(1.0, lo));
}
}
eye_sweep(ctx, l, rect, &eye_resp, actions);
if eye_resp.clicked() {