mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
Fix #45: the Project panel's details stay inside the panel
The details header (item name, size, duration, codec) and the "Select an item" hint were painted with no width limit, so in a narrow Project panel they ran past its right edge. They now stop 10 px short of it and end in "…" when they don't fit (widgets::text_fit, a shared helper), and are registered for automation (project.details.*). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
83cd5d0f45
commit
e6d4a64775
3 files changed
+40
-3
No files matched your search
@@ -212,8 +212,11 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
},
|
||||
}
|
||||
app.auto.add("project.thumbnail", thumb, &it.name);
|
||||
// The details stay inside the panel (a margin on the right), cut short with "…".
|
||||
let tx = thumb.max.x + 10.0;
|
||||
p.text(pos2(tx, thumb.min.y + 6.0), Align2::LEFT_CENTER, &it.name, Tokens::semibold(12.0), t.text);
|
||||
let max_w = head.max.x - 10.0 - tx;
|
||||
let r = widgets::text_fit(&p, pos2(tx, thumb.min.y + 6.0), Align2::LEFT_CENTER, &it.name, Tokens::semibold(12.0), max_w, t.text);
|
||||
app.auto.add("project.details.name", r, &it.name);
|
||||
let mut lines = vec![];
|
||||
if let Some((w, h)) = it.dimensions() {
|
||||
lines.push(format!("{w} x {h} (1.00)"));
|
||||
@@ -226,10 +229,13 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
lines.push(f.codec.clone());
|
||||
}
|
||||
for (i, l) in lines.iter().enumerate() {
|
||||
p.text(pos2(tx, thumb.min.y + 22.0 + 13.0 * i as f32), Align2::LEFT_CENTER, l, Tokens::ui(11.0), t.text_dim);
|
||||
let r = widgets::text_fit(&p, pos2(tx, thumb.min.y + 22.0 + 13.0 * i as f32), Align2::LEFT_CENTER, l, Tokens::ui(11.0), max_w, t.text_dim);
|
||||
app.auto.add(&format!("project.details.{i}"), r, l);
|
||||
}
|
||||
} else {
|
||||
p.text(head.center(), Align2::CENTER_CENTER, "Select an item to see its details", Tokens::ui(11.0), t.text_faint);
|
||||
let hint = "Select an item to see its details";
|
||||
let r = widgets::text_fit(&p, head.center(), Align2::CENTER_CENTER, hint, Tokens::ui(11.0), head.width() - 20.0, t.text_faint);
|
||||
app.auto.add("project.details.hint", r, hint);
|
||||
}
|
||||
// Search.
|
||||
let sr = Rect::from_min_size(pos2(rect.min.x + 8.0, head.max.y + 2.0), vec2(rect.width() - 16.0, 22.0));
|
||||
|
||||
@@ -143,6 +143,17 @@ pub fn icon_button(ui: &mut Ui, rect: Rect, icon: Icon, active: bool, t: &Tokens
|
||||
resp
|
||||
}
|
||||
|
||||
/// One line of `text` at `pos` (placed by `align`), cut short with "…" past `max_w` points so it
|
||||
/// never runs out of its panel. Returns where it was painted.
|
||||
pub fn text_fit(p: &egui::Painter, pos: egui::Pos2, align: Align2, text: &str, font: egui::FontId, max_w: f32, color: Color32) -> Rect {
|
||||
let mut job = egui::text::LayoutJob::simple_singleline(text.to_owned(), font, color);
|
||||
job.wrap = egui::text::TextWrapping { max_width: max_w.max(0.0), max_rows: 1, break_anywhere: true, overflow_character: Some('…') };
|
||||
let galley = p.layout_job(job);
|
||||
let rect = align.anchor_size(pos, galley.size());
|
||||
p.galley(rect.min, galley, color);
|
||||
rect
|
||||
}
|
||||
|
||||
/// Rounded search field with a magnifier icon.
|
||||
pub fn search_field(ui: &mut Ui, rect: Rect, text: &mut String, hint: &str, t: &Tokens) -> Response {
|
||||
let h = rect.height();
|
||||
|
||||
@@ -199,3 +199,23 @@ fn panels_dock_beside_others_and_gutters_resize_them() {
|
||||
let wider = rect(&h, "panel.Project");
|
||||
assert!((wider.width() - project.width() - 60.0).abs() < 2.0, "{} → {}", project.width(), wider.width());
|
||||
}
|
||||
|
||||
/// Issue #45: the Project panel's details (name, size, duration) stay inside the panel with a
|
||||
/// margin, cut short with "…" when they don't fit; so does the hint shown with nothing selected.
|
||||
#[test]
|
||||
fn project_details_stay_inside_the_panel() {
|
||||
let (mut h, pre, _) = harness();
|
||||
let long = "A composition with a very long name that could never fit beside the thumbnail".to_string();
|
||||
h.state_mut().session.execute("project.rename", json!({"item": pre, "name": long})).unwrap();
|
||||
h.state_mut().session.state.project_selection = vec![ItemId(pre)];
|
||||
h.run_steps(3);
|
||||
let panel = rect(&h, "panel.Project");
|
||||
for id in ["project.details.name", "project.details.0", "project.details.1"] {
|
||||
let r = rect(&h, id);
|
||||
assert!(r.max.x <= panel.max.x - 9.0 && r.width() > 10.0, "{id}: {r:?} in {panel:?}");
|
||||
}
|
||||
h.state_mut().session.state.project_selection.clear();
|
||||
h.run_steps(3);
|
||||
let r = rect(&h, "project.details.hint");
|
||||
assert!(r.min.x >= panel.min.x + 9.0 && r.max.x <= panel.max.x - 9.0, "{r:?} in {panel:?}");
|
||||
}
|
||||
Reference in new issue
Block a user