mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-14 14:26:46 -04:00
Merge pull request #397 from grovebit/mix-narrow-headers
Fit the section names in narrow Mix strips
This commit is contained in:
2 files changed
+80
-3
No files matched your search
@@ -75,8 +75,26 @@ fn channel_levels(ui: &Ui, key: (&str, u64), peaks: &[f32], n: usize) -> Vec<f32
|
||||
lv
|
||||
}
|
||||
|
||||
/// Pro Tools' names for sections in strips too narrow for the full ones.
|
||||
fn short_label(text: &str) -> &str {
|
||||
match text {
|
||||
"INSERTS A-E" => "I A-E",
|
||||
"INSERTS F-J" => "I F-J",
|
||||
"SENDS A-E" => "S A-E",
|
||||
"SENDS F-J" => "S F-J",
|
||||
"INSTRUMENT" => "INST",
|
||||
_ => text,
|
||||
}
|
||||
}
|
||||
|
||||
fn section_label(ui: &Ui, r: Rect, text: &str) {
|
||||
ui.painter().text(pos2(r.center().x, r.min.y + 7.0), Align2::CENTER_CENTER, text, bold(10.0), Tokens::current().section_label);
|
||||
let p = ui.painter();
|
||||
let color = Tokens::current().section_label;
|
||||
let mut galley = p.layout_no_wrap(text.to_owned(), bold(10.0), color);
|
||||
if galley.size().x > r.width() - 8.0 {
|
||||
galley = p.layout_no_wrap(short_label(text).to_owned(), bold(10.0), color);
|
||||
}
|
||||
p.galley(Align2::CENTER_CENTER.anchor_size(pos2(r.center().x, r.min.y + 7.0), galley.size()).min, galley, color);
|
||||
}
|
||||
|
||||
pub(crate) fn route_name(app: &SoundApp, r: &Route) -> String {
|
||||
@@ -220,7 +238,8 @@ fn strip(app: &mut SoundApp, ui: &mut Ui, id: TrackId, snap: Option<&MeterSnapsh
|
||||
let sec = Rect::from_min_size(pos2(x0, y), vec2(inner_w, 44.0));
|
||||
let mut c = track.comments.clone();
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(sec));
|
||||
if child.add(egui::TextEdit::multiline(&mut c).desired_width(inner_w).desired_rows(2).hint_text("comments").font(regular(10.0))).changed() {
|
||||
let hint = if narrow { "" } else { "comments" };
|
||||
if child.add(egui::TextEdit::multiline(&mut c).desired_width(inner_w).desired_rows(2).hint_text(hint).font(regular(10.0))).changed() {
|
||||
let _ = app.engine.execute_merged("track.comments", &json!({"track": id.0, "comments": c}), &format!("comments:{}", id.0));
|
||||
}
|
||||
y = sec.max.y + 4.0;
|
||||
@@ -268,7 +287,8 @@ fn strip(app: &mut SoundApp, ui: &mut Ui, id: TrackId, snap: Option<&MeterSnapsh
|
||||
y = sec.max.y + 4.0;
|
||||
}
|
||||
// Group selector.
|
||||
let gname = app.engine.session().groups.iter().find(|g| g.members.contains(&id)).map_or("no group".to_string(), |g| g.name.clone());
|
||||
let no_group = if narrow { "nogrp" } else { "no group" };
|
||||
let gname = app.engine.session().groups.iter().find(|g| g.members.contains(&id)).map_or(no_group.to_string(), |g| g.name.clone());
|
||||
let gr = Rect::from_min_size(pos2(x0 + 2.0, y), vec2(inner_w - 4.0, 16.0));
|
||||
let mut c = ui.new_child(egui::UiBuilder::new().max_rect(gr));
|
||||
let _ = selector_box(&mut c, gr.width(), gr.height(), &gname, t.text_dim);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
use egui::{Shape, vec2};
|
||||
use serde_json::json;
|
||||
use soundcraft_ui_egui::mix_window::strip_width;
|
||||
use soundcraft_ui_egui::{Services, SoundApp};
|
||||
|
||||
const FULL: [&str; 7] = ["INSERTS A-E", "INSERTS F-J", "SENDS A-E", "SENDS F-J", "INSTRUMENT", "comments", "no group"];
|
||||
const SHORT: [&str; 6] = ["I A-E", "I F-J", "S A-E", "S F-J", "INST", "nogrp"];
|
||||
|
||||
fn painted_labels(narrow: bool) -> Vec<(String, f32, bool)> {
|
||||
let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default());
|
||||
app.run("window.mix", json!({})).unwrap();
|
||||
app.run("view.mix_section", json!({"section": "all"})).unwrap();
|
||||
app.run("view.mix_section", json!({"section": "instruments"})).unwrap();
|
||||
app.ui.narrow_mix = narrow;
|
||||
let mut harness = egui_kittest::Harness::builder().with_size(vec2(1600.0, 1000.0)).build_ui_state(
|
||||
|ui, app: &mut SoundApp| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
},
|
||||
app,
|
||||
);
|
||||
for _ in 0..4 {
|
||||
harness.step();
|
||||
}
|
||||
harness
|
||||
.output()
|
||||
.shapes
|
||||
.iter()
|
||||
.filter_map(|s| match &s.shape {
|
||||
Shape::Text(t) if FULL.contains(&t.galley.job.text.as_str()) || SHORT.contains(&t.galley.job.text.as_str()) => {
|
||||
Some((t.galley.job.text.clone(), t.visual_bounding_rect().width(), t.galley.elided))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn narrow_strips_use_short_section_names_that_fit() {
|
||||
let labels = painted_labels(true);
|
||||
for name in SHORT {
|
||||
assert!(labels.iter().any(|(text, ..)| text == name), "{name} missing in {labels:?}");
|
||||
}
|
||||
for (text, width, elided) in &labels {
|
||||
assert!(SHORT.contains(&text.as_str()), "{text} painted in a narrow strip, where it doesn't fit");
|
||||
assert!(*width <= strip_width(true) - 16.0 && !elided, "{text} is {width} pt wide, elided: {elided}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normal_strips_keep_the_full_section_names() {
|
||||
let labels = painted_labels(false);
|
||||
for name in FULL {
|
||||
assert!(labels.iter().any(|(text, ..)| text == name), "{name} missing in {labels:?}");
|
||||
}
|
||||
assert!(labels.iter().all(|(text, ..)| FULL.contains(&text.as_str())), "{labels:?}");
|
||||
}
|
||||
Reference in new issue
Block a user