Files
soundcraft/crates/ui-egui/tests/zoom_toggle.rs
grovebit e26a5f5f42 Zoom Toggle: E zooms in on the edit selection, E again zooms back out
In Pro Tools, E (with Commands Keyboard Focus on) zooms the Edit window
to the edit selection and fits the selected tracks to the window, and
pressing it again brings back the view from before. SoundCraft had no
Zoom Toggle.

view.zoom_toggle, in its own command module, stores the zoom, the
scroll and the selected tracks' heights in the session's new
edit.zoom_toggle, so the view to go back to is saved with the session.
It then zooms so the selection fills the timeline and gives the
selected tracks equal shares of the track area: Pro Tools' Fit To
Window height. Hidden tracks are left alone. Run again, it puts all of
that back. With only an insertion point the zoom stays and its tracks
are fitted. The UI passes the track area's size; agents can pass
width_px and height_px.

TrackHeight::Fit, which nothing could reach and which drew 88 points
tall, now carries its height in points, so every place that sizes a
track row reads it unchanged.

The Edit window scrolls the first fitted track to the top when Zoom
Toggle turns on, and back to where it was when it turns off, whichever
way it was toggled (key, button, control channel, undo).

As in Pro Tools, E works in the Edit window while Commands Keyboard
Focus (the a-z button) is on, on every OS. A Zoom Toggle button left of
the Zoomer lights while it is on and toggles it too.

This follows Pro Tools' Zoom Toggle settings for audio editing:
Selection for both zooms, Fit To Window, no track view change. Its
other preferences, Ctrl+E (Pro Tools' key with the focus off),
Alt+Shift+E (cancel) and following the edit selection are left out.

Tests cover the zoom, the fitted heights, going back, insertion points,
hostile sizes and stored views, and E and the toolbar button on macOS,
Windows and Linux.
2026-10-12 01:22:08 +01:00

44 lines
2.0 KiB
Rust

use egui::os::OperatingSystem;
use egui::{Key, vec2};
use egui_kittest::{Harness, kittest::Queryable};
use serde_json::json;
use soundcraft_ui_egui::{Services, SoundApp};
#[test]
fn e_fits_the_selection_to_the_edit_window_and_the_button_goes_back() {
for os in [OperatingSystem::Mac, OperatingSystem::Windows, OperatingSystem::Nix] {
let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default());
let bass = app.engine.session().track_by_name("Bass").unwrap().id.0;
app.engine.execute("edit.select", &json!({"tracks": [bass], "start": 96_000, "end": 192_000})).unwrap();
let mut h = Harness::builder().with_size(vec2(1600.0, 1000.0)).with_os(os).build_ui_state(
|ui, app: &mut SoundApp| {
app.logic(&ui.ctx().clone());
app.ui(ui);
},
app,
);
h.run_steps(5);
let view = |a: &SoundApp| (a.engine.session().edit.zoom, a.edit_layout.rows.clone(), a.edit_layout.scroll_y);
let before = view(h.state());
h.state_mut().engine.execute("options.keyboard_focus", &json!({"focus": "none"})).unwrap();
h.key_press(Key::E);
h.run_steps(1);
assert_eq!(view(h.state()), before, "{os:?}");
h.state_mut().engine.execute("options.keyboard_focus", &json!({"focus": "commands"})).unwrap();
h.key_press(Key::E);
h.run_steps(1);
let [x0, y0, x1, y1] = h.state().edit_layout.timeline;
let zoom = h.state().engine.session().edit.zoom;
assert_eq!(zoom.scroll, 96_000, "{os:?}");
assert!((f64::from(x1 - x0) * zoom.samples_per_px - 96_000.0).abs() < 1.0, "{os:?}");
let row = h.state().edit_layout.rows.iter().find(|(id, _)| *id == bass).unwrap().1;
assert_eq!(row[1], y0, "{os:?}");
assert!((row[3] + 1.0 - y1).abs() < 1.0, "{os:?}: {row:?} in {y0}..{y1}");
h.get_by_label("Zoom Toggle (E)").click();
h.run_steps(1);
assert_eq!(view(h.state()), before, "{os:?}");
}
}