fix(ui): double-clicking a track's colour strip opens the Color Palette (#1254)

The colour strip at the left of an Edit-window track header now has its own
click area. A double-click selects the track, keeping a multi-selection it
is part of, and opens Window > Color Palette, which colours the selected
tracks. A click on an unselected track's strip selects it as the header
did; a plain click on an already selected track's strip leaves the selection
alone, so a double-click can colour several tracks. Right-click still opens
the track menu.

Co-Authored-By: Rahul <rahulsingh.ranjan06@gmail.com>
This commit is contained in:
Zinadin ZidanandRahul committed 2026-11-06 00:50:57 +06:00
1 parent 73eeb692fe
commit fca0130b72
2 files changed
+71

No files matched your search

+24
View File
@@ -1,3 +1,4 @@
use super::layout::STRIP_W;
use super::tracks::{click_track, folder_depth, height_targets, in_edit_window, track_context_menu, view_label, view_menu};
use super::{
Align2, AutoParam, Color32, Pos2, Rect, Sense, Shape, SoundApp, Stroke, Tokens, Track, TrackHeight, TrackId, TrackKind, Ui, bold, groove, json,
@@ -14,6 +15,7 @@ pub(super) fn track_header(app: &mut SoundApp, ui: &mut Ui, track: &Track, head:
click_track(app, id, ui.input(|i| i.modifiers), in_edit_window);
}
bg.context_menu(|ui| track_context_menu(app, ui, id));
color_strip(app, ui, id, head);
resize_edge(app, ui, track, head);
strip_buttons(app, ui, track, head);
name_plate(app, ui, track, head, selected);
@@ -26,6 +28,28 @@ pub(super) fn track_header(app: &mut SoundApp, ui: &mut Ui, track: &Track, head:
header_meter(ui, Rect::from_min_max(pos2(head.max.x - 8.0, head.min.y + 1.0), pos2(head.max.x, head.max.y - 1.5)), &md, track.channels() >= 2);
}
/// The colour strip: a click selects the track as the header does, a double click opens the Color
/// Palette for the selected tracks. A plain click on a track that is already selected keeps the
/// selection, so double-clicking one of several selected tracks colours them all. Registered after
/// the header background, so it sits on top of it, and before the strip's own buttons and the
/// resize edge, which stay on top of it.
fn color_strip(app: &mut SoundApp, ui: &mut Ui, id: TrackId, head: Rect) {
let strip = Rect::from_min_size(head.min, vec2(STRIP_W, head.height()));
let resp = ui.interact(strip, ui.scope_id().with(("color_strip", id.0)), Sense::click());
let mods = ui.input(|i| i.modifiers);
let selected = app.engine.session().edit.selected_tracks.contains(&id);
if resp.double_clicked() {
// A Cmd click toggles, so a Cmd double click's first click deselected the track: add it back.
if !selected {
click_track(app, id, mods, in_edit_window);
}
app.ui.show_color_palette = true;
} else if resp.clicked() && !(selected && mods.is_none()) {
click_track(app, id, mods, in_edit_window);
}
resp.context_menu(|ui| track_context_menu(app, ui, id));
}
/// Drag the bottom edge of the header to resize the track (snaps to the height presets).
fn resize_edge(app: &mut SoundApp, ui: &mut Ui, track: &Track, head: Rect) {
let id = track.id;
+47
View File
@@ -534,6 +534,53 @@ fn shift_and_cmd_click_on_track_names_extend_the_selection() {
}
}
/// #1254: double-clicking a track's colour strip selects the track and opens the Color Palette;
/// a single click only selects it.
#[test]
fn double_clicking_the_color_strip_opens_the_color_palette() {
let mut h = harness(3);
let ids = row_ids(&h);
let strip = |h: &Harness<SoundApp>, i: usize| pos2(row(h, i).min.x + layout::STRIP_W / 2.0, row(h, i).center().y);
h.state_mut().engine.execute("edit.select", &json!({"tracks": [ids[0].0]})).unwrap();
h.run_steps(2);
let at = strip(&h, 1);
click(&mut h, at);
assert_eq!(h.state().engine.session().edit.selected_tracks, [ids[1]]);
assert!(!h.state().ui.show_color_palette, "a single click on the strip doesn't open the palette");
h.run_steps(30);
let at = strip(&h, 2);
click(&mut h, at);
click(&mut h, at);
assert_eq!(h.state().engine.session().edit.selected_tracks, [ids[2]]);
assert!(h.state().ui.show_color_palette, "a double click on the strip opens the palette");
}
/// #1254: a double click on the strip of one of several selected tracks keeps them all selected,
/// so the palette colours every one; with Cmd held the double-clicked track ends selected too.
#[test]
fn double_clicking_a_selected_tracks_strip_keeps_the_selection() {
let mut h = harness(3);
let ids = row_ids(&h);
let strip = |h: &Harness<SoundApp>, i: usize| pos2(row(h, i).min.x + layout::STRIP_W / 2.0, row(h, i).center().y);
h.state_mut().engine.execute("edit.select", &json!({"tracks": [ids[0].0, ids[2].0]})).unwrap();
h.run_steps(2);
let at = strip(&h, 2);
click(&mut h, at);
assert_eq!(h.state().engine.session().edit.selected_tracks, [ids[0], ids[2]], "a plain click on a selected strip keeps the selection");
assert!(!h.state().ui.show_color_palette);
click(&mut h, at);
assert_eq!(h.state().engine.session().edit.selected_tracks, [ids[0], ids[2]], "both tracks stay selected");
assert!(h.state().ui.show_color_palette, "a double click on the strip opens the palette");
h.state_mut().ui.show_color_palette = false;
h.run_steps(30);
let at = strip(&h, 0);
click_with(&mut h, at, egui::Modifiers::COMMAND);
click_with(&mut h, at, egui::Modifiers::COMMAND);
assert!(h.state().engine.session().edit.selected_tracks.contains(&ids[0]), "a Cmd double click leaves its track selected");
assert!(h.state().ui.show_color_palette, "a Cmd double click on the strip opens the palette");
}
#[test]
fn a_quick_drag_from_a_clip_edge_trims_it() {
let mut h = smart_demo();