Brush Settings: no section title above the options pane (#3477) (#5017)

* Brush Settings: no section title above the options pane (#3477)

The options pane repeated the selected section's name as a title line.
The selected row in the section list already names it, as in Photoshop,
so the title is gone and the options start at the top of the pane.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* i18n test: the brush section name is drawn once, without a heading (#3477)

dynamic_brush_sections_have_translations_and_draw_in_the_selected_language
still expected the translated section name twice: the list row and the
options pane heading this branch removes. It now expects the row alone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Michael HigginsandClaude Opus 5.5 authored and GitHub committed 2026-10-13 12:01:40 -04:00
1 parent 1304765067
commit 6f9227efa3
3 files changed
+27 -8

No files matched your search

+3 -4
View File
@@ -14,7 +14,7 @@
//! The lock beside a section name keeps that section's settings when another preset is picked
//! (`locks` in the brush, applied by the engine). The Brushes tab lives in [`crate::brushes_tab`].
use egui::{Color32, CornerRadius, RichText, Sense, Stroke, vec2};
use egui::{Color32, CornerRadius, Sense, Stroke, vec2};
use photocraft_engine::BrushSettings;
use photocraft_engine::paint;
use serde::{Deserialize, Serialize};
@@ -359,9 +359,8 @@ fn settings_tab(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
widgets::vline(ui, 482.0);
ui.vertical(|ui| {
ui.set_width(WIDTH - 190.0);
let name = SECTIONS.get(section).map_or("Brush Tip Shape", |entry| entry.0);
ui.label(RichText::new(tl!(name)).font(theme::semibold(12.5)).color(t.text));
ui.add_space(6.0);
// No title above the options (#3477): the selected row in the list names them, as
// in Photoshop, and the line is better spent on the options.
let on = section_flag(&mut b, section).is_none_or(|f| *f);
egui::ScrollArea::vertical().id_salt(("brush-section", section)).max_height(450.0).auto_shrink([false, false]).show(ui, |ui| {
ui.set_width(WIDTH - 204.0);
+22 -3
View File
@@ -992,7 +992,7 @@ fn app_harness_with_language(lang: crate::i18n::Lang) -> Harness<'static, Photoc
}
#[test]
fn brush_sections_paint_simplified_chinese_labels_and_heading() {
fn brush_sections_paint_simplified_chinese_labels() {
fn collect_text(shape: &egui::Shape, out: &mut Vec<String>) {
match shape {
egui::Shape::Text(text) => out.push(text.galley.job.text.clone()),
@@ -1017,8 +1017,27 @@ fn brush_sections_paint_simplified_chinese_labels_and_heading() {
assert!(painted.iter().any(|s| s == translated), "{name} must paint as {translated}");
assert!(!painted.iter().any(|s| s == name), "{name} must not paint in English");
}
let heading = crate::i18n::tr(zh, "Brush Tip Shape");
assert_eq!(painted.iter().filter(|s| s.as_str() == heading).count(), 2, "both the section row and heading are translated");
}
/// #3477: the options pane has no title of its own. The selected row in the section list is the
/// only place the section's name is painted.
#[test]
fn options_pane_does_not_repeat_the_selected_sections_name() {
fn collect_text(shape: &egui::Shape, out: &mut Vec<String>) {
match shape {
egui::Shape::Text(text) => out.push(text.galley.job.text.clone()),
egui::Shape::Vec(shapes) => shapes.iter().for_each(|s| collect_text(s, out)),
_ => {}
}
}
for (section, (name, _)) in SECTIONS.iter().enumerate().take(CHECKBOX_ONLY_START) {
let h = harness(0, section);
let mut painted = Vec::new();
for shape in &h.output().shapes {
collect_text(&shape.shape, &mut painted);
}
assert_eq!(painted.iter().filter(|s| s.as_str() == *name).count(), 1, "{name} is painted once, in the section list");
}
}
#[test]
+2 -1
View File
@@ -93,7 +93,8 @@ fn dynamic_brush_sections_have_translations_and_draw_in_the_selected_language()
h.state_mut().ui.panels.brush_settings = true;
h.run_steps(4);
let text = drawn_text(&h);
assert!(text.iter().filter(|text| text.as_str() == "画笔笔尖形状").count() >= 2, "both the section row and heading must be translated");
// The section row is the only place the name is drawn: the options pane has no heading (#3477).
assert_eq!(text.iter().filter(|text| text.as_str() == "画笔笔尖形状").count(), 1, "the section row must be translated");
assert!(!text.iter().any(|text| text == "Brush Tip Shape"));
});
}