Tracks and Groups list rows publish their names to AccessKit (fixes #651)

This commit is contained in:
Marco Arnulfo
2026-10-16 04:39:08 +02:00
parent ba467b2b72
commit d484a716ad
3 changed files with 58 additions and 1 deletions
+3
View File
@@ -66,6 +66,7 @@ pub fn tracks_and_groups(app: &mut SoundApp, ui: &mut Ui) {
let out = lists.show(ui, |ui| {
for (id, name, shown, color, sel) in tracks {
let (r, resp) = ui.allocate_exact_size(vec2(ui.available_width(), 17.0), Sense::click_and_drag());
resp.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::SelectableLabel, true, sel, &name));
if sel {
ui.painter().rect_filled(r, 0.0, t.row_selected);
}
@@ -94,6 +95,7 @@ pub fn tracks_and_groups(app: &mut SoundApp, ui: &mut Ui) {
let (r, _) = ui.allocate_exact_size(vec2(ui.available_width(), 17.0), Sense::hover());
ui.painter().text(pos2(r.min.x + 30.0, r.center().y), Align2::LEFT_CENTER, "<ALL>", regular(11.5).clone(), t.text);
let all = ui.interact(r, ui.id().with("group_all"), Sense::click());
all.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, "<ALL>"));
if all.double_clicked() {
let _ = app.run("edit.select_all", json!({}));
}
@@ -105,6 +107,7 @@ pub fn tracks_and_groups(app: &mut SoundApp, ui: &mut Ui) {
});
for (id, letter, name, active, color) in groups {
let (r, resp) = ui.allocate_exact_size(vec2(ui.available_width(), 17.0), Sense::click());
resp.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::Checkbox, true, active, &name));
if active {
ui.painter().rect_filled(Rect::from_min_size(pos2(r.min.x + 4.0, r.min.y + 2.0), vec2(14.0, 13.0)), 1.0, rgb(color));
}
@@ -177,7 +177,7 @@ fn populated_mix_instrument_uses_readable_palette_in_real_frames() {
harness.step();
}
harness.step(); // Let the popup finish its initial sizing pass.
harness.get_by_label_contains("Built-in").hover();
harness.get_by_label("Built-in ⏵").hover();
harness.step();
harness.step();
harness.get_by_label("Drum Synth").click();
+54
View File
@@ -0,0 +1,54 @@
//! #651: the Tracks and Groups lists publish their rows to AccessKit, by name, so screen readers
//! can read them and tests can reach them by label instead of by geometry.
use egui::accesskit::{Role, Toggled};
use egui::vec2;
use egui_kittest::{
Harness,
kittest::{NodeT, Queryable},
};
use serde_json::json;
use soundcraft_ui_egui::{Services, SoundApp};
fn harness() -> Harness<'static, SoundApp> {
let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default());
let first = app.engine.session().tracks.first().map(|t| t.id.0).unwrap_or_default();
app.run("track.group", json!({"name": "Rhythm", "tracks": [first]})).unwrap();
app.engine.session_mut().edit.selected_tracks.clear();
let mut h = Harness::builder().with_size(vec2(1600.0, 1000.0)).build_ui_state(
|ui, app: &mut SoundApp| {
let ctx = ui.ctx().clone();
app.logic(&ctx);
app.ui(ui);
},
app,
);
h.run_steps(3);
h
}
#[test]
fn tracks_list_rows_are_named_and_report_their_selection() {
let mut h = harness();
let tracks: Vec<(u64, String)> = h.state().engine.session().tracks.iter().map(|t| (t.id.0, t.name.clone())).collect();
assert!(tracks.len() >= 2);
for (_, name) in &tracks {
assert_eq!(h.get_by_role_and_label(Role::Button, name).accesskit_node().toggled(), Some(Toggled::False), "{name}");
}
let (id, name) = &tracks[1];
h.get_by_role_and_label(Role::Button, name).click();
h.run_steps(2);
assert_eq!(h.state().engine.session().edit.selected_tracks.iter().map(|t| t.0).collect::<Vec<_>>(), vec![*id]);
assert_eq!(h.get_by_role_and_label(Role::Button, name).accesskit_node().toggled(), Some(Toggled::True));
}
#[test]
fn groups_list_rows_are_named_and_report_whether_the_group_is_active() {
let mut h = harness();
h.get_by_label("<ALL>");
assert_eq!(h.get_by_role_and_label(Role::CheckBox, "Rhythm").accesskit_node().toggled(), Some(Toggled::True));
h.get_by_role_and_label(Role::CheckBox, "Rhythm").click();
h.run_steps(2);
assert!(h.state().engine.session().groups.iter().all(|g| !g.active));
assert_eq!(h.get_by_role_and_label(Role::CheckBox, "Rhythm").accesskit_node().toggled(), Some(Toggled::False));
}