Make the Zoom Preset, Waveform Zoom and Clip Rating keys work; add Commands Focus 1-5 and N

From #186: waveform zoom could not be zoomed back out, zoom presets had
no keys, and N did nothing for Insertion Follows Playback.

The registry writes three shortcuts as key families: "Cmd+Ctrl+1-5"
(Zoom Preset), "Cmd+Alt+0-5" (Clip Rating) and "Cmd+Alt+[ / ]"
(Waveform Zoom). The shortcut parser can't read them, so they never
fired. The menus still showed them.

- The keyboard handler takes these keys itself, as it does F1-F4:
  Cmd+Alt+[ and ] zoom the waveforms out and in, Cmd+Alt+0-5 rate the
  selected clips and Cmd+Ctrl+1-5 recall the zoom presets. Other digits
  do nothing.
- Waveform Zoom and Clip Rating work on every OS (Ctrl+Alt on Windows
  and Linux). Cmd+Ctrl+1-5 stays a macOS key, like the other Mac
  Control chords, which the shortcut list already leaves out off macOS.
- Commands Focus (the a-z button) gains Pro Tools' 1-5 for the zoom
  presets and N for Insertion Follows Playback, on every OS.
This commit is contained in:
grovebit
2026-10-12 17:19:46 +01:00
parent df0c4790b7
commit 35609b756b
2 changed files with 86 additions and 0 deletions
+23
View File
@@ -175,6 +175,20 @@ fn fixed(app: &mut SoundApp, key: Key, m: Modifiers, mac: bool) -> bool {
}
true
}
// The registry's key families "Cmd+Alt+[ / ]", "Cmd+Alt+0-5" and "Cmd+Ctrl+1-5", which `parse` can't read.
Key::OpenBracket | Key::CloseBracket if mods_match(Modifiers::COMMAND | Modifiers::ALT, m, mac) => {
let factor = if key == Key::CloseBracket { 2.0 } else { 0.5 };
let _ = app.run("view.waveform_zoom", json!({"factor": factor}));
true
}
Key::Num0 | Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 if mods_match(Modifiers::COMMAND | Modifiers::ALT, m, mac) => {
let _ = app.run("clip.rating", json!({"rating": digit(key)}));
true
}
Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 if mods_match(Modifiers::COMMAND | Modifiers::CTRL, m, mac) => {
let _ = app.run("view.zoom_preset", json!({"preset": digit(key)}));
true
}
Key::ArrowUp | Key::ArrowDown if m.ctrl && !m.shift => {
let id = if key == Key::ArrowUp { "edit.extend_selection_up" } else { "edit.extend_selection_down" };
let _ = app.run(id, json!({}));
@@ -211,6 +225,11 @@ fn commands_focus(app: &mut SoundApp, key: Key) -> bool {
Key::C => "edit.copy",
Key::V => "edit.paste",
Key::Z => "edit.undo",
Key::N => "options.insertion_follows_playback",
Key::Num1 | Key::Num2 | Key::Num3 | Key::Num4 | Key::Num5 => {
let _ = app.run("view.zoom_preset", json!({"preset": digit(key)}));
return true;
}
Key::P => {
move_selection_track(app, -1);
return true;
@@ -255,6 +274,10 @@ fn tab_clip(app: &mut SoundApp, back: bool) {
}
}
fn digit(key: Key) -> u8 {
key.name().parse().unwrap_or(0)
}
/// Shortcut text for display. The registry stores macOS-style strings ("Cmd+N"); off macOS the Cmd
/// modifier is the Ctrl key. Mac-only Control chords ("Cmd+Ctrl+S") have no key there, so they show nothing.
pub fn shortcut_label(s: &str, mac: bool) -> String {
+63
View File
@@ -0,0 +1,63 @@
//! Shortcuts written as key families ("Cmd+Ctrl+1-5", "Cmd+Alt+0-5", "Cmd+Alt+[ / ]") fire, and Commands Focus
//! has Pro Tools' 1–5 zoom presets and N for Insertion Follows Playback.
use egui::os::OperatingSystem;
use egui::{Key, Modifiers};
use serde_json::json;
use soundcraft_ui_egui::{Services, SoundApp, shortcuts};
const MAC_CMD: Modifiers = Modifiers { mac_cmd: true, command: true, ..Modifiers::NONE };
const PC_CTRL: Modifiers = Modifiers { ctrl: true, command: true, ..Modifiers::NONE };
const OSES: [(OperatingSystem, Modifiers); 3] =
[(OperatingSystem::Mac, MAC_CMD), (OperatingSystem::Windows, PC_CTRL), (OperatingSystem::Nix, PC_CTRL)];
fn press(ctx: &egui::Context, app: &mut SoundApp, key: Key, modifiers: Modifiers) {
let events = [true, false].map(|pressed| egui::Event::Key { key, physical_key: None, pressed, repeat: false, modifiers }).to_vec();
ctx.run_ui(egui::RawInput { events, ..Default::default() }, |ui| shortcuts::handle(app, ui.ctx())).textures_delta.clear();
}
fn rig(os: OperatingSystem) -> (egui::Context, SoundApp) {
let ctx = egui::Context::default();
ctx.set_os(os);
(ctx, SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default()))
}
#[test]
fn cmd_alt_brackets_zoom_waveforms_and_cmd_alt_digits_rate_clips() {
for (os, cmd) in OSES {
let (ctx, mut app) = rig(os);
let cmd_alt = Modifiers { alt: true, ..cmd };
press(&ctx, &mut app, Key::CloseBracket, cmd_alt);
press(&ctx, &mut app, Key::CloseBracket, cmd_alt);
press(&ctx, &mut app, Key::OpenBracket, cmd_alt);
assert_eq!(app.engine.session().edit.zoom.waveform_zoom, 2.0, "{os:?}");
let kick = app.engine.session().track_by_name("Kick").unwrap().clips()[0].id;
app.engine.execute("edit.select", &json!({"clips": [kick.0]})).unwrap();
press(&ctx, &mut app, Key::Num4, cmd_alt);
assert_eq!(app.engine.session().find_clip(kick).unwrap().1.rating, 4, "{os:?}");
press(&ctx, &mut app, Key::Num9, cmd_alt);
assert_eq!(app.engine.session().find_clip(kick).unwrap().1.rating, 4, "{os:?}: 9 is outside 0-5");
}
}
#[test]
fn cmd_ctrl_digits_recall_zoom_presets_on_macos() {
let (ctx, mut app) = rig(OperatingSystem::Mac);
press(&ctx, &mut app, Key::Num2, Modifiers { ctrl: true, ..MAC_CMD });
assert_eq!(app.engine.session().edit.zoom.samples_per_px, 256.0);
press(&ctx, &mut app, Key::Num6, Modifiers { ctrl: true, ..MAC_CMD });
assert_eq!(app.engine.session().edit.zoom.samples_per_px, 256.0, "6 is outside 1-5");
}
#[test]
fn commands_focus_digits_recall_zoom_presets_and_n_toggles_insertion_follows_playback() {
for (os, _) in OSES {
let (ctx, mut app) = rig(os);
app.engine.execute("options.keyboard_focus", &json!({"focus": "commands"})).unwrap();
let follows = app.engine.session().edit.insertion_follows_playback;
press(&ctx, &mut app, Key::Num5, Modifiers::NONE);
press(&ctx, &mut app, Key::N, Modifiers::NONE);
let edit = &app.engine.session().edit;
assert_eq!((edit.zoom.samples_per_px, edit.insertion_follows_playback), (16384.0, !follows), "{os:?}");
}
}