mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
LR-PROF-BROWSER: long profile names are cut short in a narrow panel (fixes #1634)
This commit is contained in:
@@ -109,6 +109,8 @@ mod tests_preset_import;
|
||||
#[cfg(test)]
|
||||
mod tests_preview_limit;
|
||||
#[cfg(test)]
|
||||
mod tests_profiles_layout;
|
||||
#[cfg(test)]
|
||||
mod tests_quit_unsaved;
|
||||
#[cfg(test)]
|
||||
mod tests_sam_setup;
|
||||
|
||||
@@ -12,7 +12,7 @@ use super::presets::cover_uv;
|
||||
use crate::icons::{Icon, paint};
|
||||
use crate::state::RightPanel;
|
||||
use crate::theme::Tokens;
|
||||
use crate::widgets::{divider, icon_button, register};
|
||||
use crate::widgets::{divider, icon_button, one_line, register};
|
||||
use crate::{HoverPreview, LightcraftApp};
|
||||
|
||||
/// Long edge of the variant thumbnails (px).
|
||||
@@ -35,13 +35,9 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui, id: PhotoId) {
|
||||
let (cr, _) = ui.allocate_exact_size(vec2(ui.available_width(), 34.0), Sense::hover());
|
||||
let name = app.session.profile_info(&d.profile.id).map(|(name, _)| name).unwrap_or("Color");
|
||||
ui.painter().text(pos2(cr.left() + 24.0, cr.center().y), Align2::LEFT_CENTER, crate::i18n::tr("Profile"), t.font(13.0), t.text_dim);
|
||||
ui.painter().text(
|
||||
pos2(cr.left() + 84.0, cr.center().y),
|
||||
Align2::LEFT_CENTER,
|
||||
crate::i18n::profile_label(&d.profile.id, name),
|
||||
t.font(14.0),
|
||||
t.text_label,
|
||||
);
|
||||
// a long name is cut short (with …) at the panel's edge
|
||||
let g = one_line(ui.painter(), crate::i18n::profile_label(&d.profile.id, name), t.font(14.0), t.text_label, cr.width() - 84.0 - 24.0);
|
||||
ui.painter().galley(pos2(cr.left() + 84.0, cr.center().y - g.size().y / 2.0), g, t.text_label);
|
||||
if d.profile.id != "lc.color" {
|
||||
super::edit::control(app, ui, &d, "profile.amount", true);
|
||||
ui.add_space(6.0);
|
||||
@@ -174,13 +170,9 @@ fn cell_ui(
|
||||
painter.rect_stroke(thumb, 3.0, Stroke::new(1.0, t.text_dim), egui::StrokeKind::Outside);
|
||||
}
|
||||
let name_color = if applied { t.text } else { t.text_label };
|
||||
painter.text(
|
||||
pos2(cell.left() + 2.0, thumb.bottom() + 12.0),
|
||||
Align2::LEFT_CENTER,
|
||||
crate::i18n::profile_label(p_id, p_name),
|
||||
t.font(12.0),
|
||||
name_color,
|
||||
);
|
||||
// cut short (with …) to the cell, so it never runs into its neighbour; the full name on hover
|
||||
let g = one_line(painter, crate::i18n::profile_label(p_id, p_name), t.font(12.0), name_color, cell.width() - 2.0);
|
||||
painter.galley(pos2(cell.left() + 2.0, thumb.bottom() + 12.0 - g.size().y / 2.0), g, name_color);
|
||||
// favourite star (always shown when set, on hover otherwise)
|
||||
let fav = app.session.profile_favorites.iter().any(|f| f == p_id);
|
||||
let star = Rect::from_center_size(pos2(thumb.right() - 13.0, thumb.top() + 13.0), vec2(20.0, 20.0));
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
//! The profile browser in a narrow right panel: names stay inside their cells (#1634).
|
||||
|
||||
use egui::{Rect, pos2, vec2};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{LightcraftApp, Services, headless::HeadlessView};
|
||||
|
||||
const LONG_ID: &str = "lut:kodak-portra-400-plus-one-stop-overexposed";
|
||||
const LONG_NAME: &str = "Kodak Portra 400 Plus One Stop Overexposed";
|
||||
|
||||
fn text_shapes(shape: &egui::Shape, out: &mut Vec<egui::epaint::TextShape>) {
|
||||
match shape {
|
||||
egui::Shape::Text(text) => out.push(text.clone()),
|
||||
egui::Shape::Vec(shapes) => shapes.iter().for_each(|s| text_shapes(s, out)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn panel(width: f32) -> (Vec<egui::epaint::TextShape>, Vec<(String, Rect)>) {
|
||||
let mut app = LightcraftApp::new(lightcraft_engine::Session::with_demo(), Services::default());
|
||||
app.session.lut_profiles.push(lightcraft_engine::cmd::lut_profiles::LutProfile {
|
||||
id: LONG_ID.into(),
|
||||
name: LONG_NAME.into(),
|
||||
group: "Film Stocks".into(),
|
||||
file: String::new(),
|
||||
});
|
||||
app.run("develop.profile", json!({"id": LONG_ID})).unwrap();
|
||||
let photo = app.session.active().unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
crate::theme::apply(&ctx);
|
||||
let mut texts = Vec::new();
|
||||
let mut widgets = Vec::new();
|
||||
for frame in 0..3 {
|
||||
let raw = HeadlessView::raw_input(vec2(width, 4000.0), 1.0, frame as f64 / 60.0, vec![]);
|
||||
let mut out = ctx.run_ui(raw, |ui| {
|
||||
egui::CentralPanel::default().frame(egui::Frame::NONE).show(ui, |ui| {
|
||||
crate::panels::profiles::show(&mut app, ui, photo);
|
||||
});
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
texts.clear();
|
||||
for shape in &out.shapes {
|
||||
text_shapes(&shape.shape, &mut texts);
|
||||
}
|
||||
widgets = crate::widgets::take_registry(&ctx);
|
||||
}
|
||||
(texts, widgets)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_names_stay_inside_their_cells_in_a_narrow_panel() {
|
||||
let width = 250.0;
|
||||
let (texts, widgets) = panel(width);
|
||||
let cell = widgets.iter().find(|(id, _)| id == &format!("profileCell:{LONG_ID}")).unwrap().1;
|
||||
// the cell's name sits below its thumbnail; the header's copy is above every cell
|
||||
let name = texts.iter().find(|t| t.galley.job.text == LONG_NAME && t.pos.y >= cell.top()).unwrap();
|
||||
assert!(name.galley.elided, "a name wider than its cell is cut short");
|
||||
let bounds = name.visual_bounding_rect();
|
||||
assert!(bounds.left() >= cell.left() && bounds.right() <= cell.right(), "{bounds:?} spills out of {cell:?}");
|
||||
let applied = texts.iter().find(|t| t.galley.job.text == LONG_NAME && t.pos.y < cell.top()).unwrap();
|
||||
assert!(applied.visual_bounding_rect().right() <= width, "the applied profile's name leaves the panel");
|
||||
// built-in names too: each one stays out of its neighbour's cell
|
||||
for p in lightcraft_engine::presets::PROFILES {
|
||||
let cell = widgets.iter().find(|(id, _)| id == &format!("profileCell:{}", p.id)).unwrap().1;
|
||||
let name = texts.iter().find(|t| t.galley.job.text == p.name && cell.contains(pos2(cell.center().x, t.pos.y))).unwrap();
|
||||
let bounds = name.visual_bounding_rect();
|
||||
assert!(bounds.left() >= cell.left() && bounds.right() <= cell.right(), "{}: {bounds:?} spills out of {cell:?}", p.name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user