mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-25 19:06:47 -06:00
fix(ui): fitting Intensity translations; cut values end in "…", cut labels show on hover (#256)
From review: - ru and pt-BR "Intensity" were too long for the glass field and ended in "…"; they are now "Яркость" and "Brilho", which fit. - A value too long for its field ends in "…" instead of being clipped, so "100000" never shows as "10". - A label cut short shows whole on hover. - The every-language test now checks the Intensity label fits whole in each catalog (it fails with the old ru translation); the panel test checks the label isn't cut and that the field is the 98.5 points the language test measures against. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a672a6650f
commit
7b9ebaacbb
@@ -614,7 +614,7 @@ status = "draft — needs native review"
|
||||
"Instance swap (no other component)" = "Troca de instância (nenhum outro componente)"
|
||||
"Instances" = "Instâncias"
|
||||
"Instant" = "Instantâneo"
|
||||
"Intensity" = "Intensidade"
|
||||
"Intensity" = "Brilho"
|
||||
"Interaction" = "Interação"
|
||||
"Interactions" = "Interações"
|
||||
"Interface design and prototyping. A free, open-source, clean-room design tool written from scratch in Rust, part of the ArtCraft Crafting Apps." = "Design de interfaces e prototipagem. Uma ferramenta de design gratuita e de código aberto, com implementação independente (clean-room), escrita do zero em Rust, parte dos Crafting Apps da ArtCraft."
|
||||
|
||||
@@ -635,7 +635,7 @@ name = "Русский"
|
||||
"Instance swap (no other component)" = "Замена экземпляра (других компонентов нет)"
|
||||
"Instances" = "Экземпляры"
|
||||
"Instant" = "Мгновенно"
|
||||
"Intensity" = "Интенсивность"
|
||||
"Intensity" = "Яркость"
|
||||
"Interaction" = "Взаимодействие"
|
||||
"Interactions" = "Взаимодействия"
|
||||
"Interface design and prototyping. A free, open-source, clean-room design tool written from scratch in Rust, part of the ArtCraft Crafting Apps." = "Дизайн интерфейсов и прототипирование. Бесплатный инструмент с открытым исходным кодом, независимо созданный с нуля на Rust, из семейства ArtCraft Crafting Apps."
|
||||
|
||||
@@ -502,34 +502,31 @@ fn the_glass_light_intensity_field_has_a_label() {
|
||||
u.frame(vec![]);
|
||||
let shapes = u.frame_output(vec![]).shapes;
|
||||
let lead = u.ctx.read_response(Id::new(("fx_gi", 0usize)).with("lead")).expect("the intensity field is shown").rect;
|
||||
let labels: Vec<String> = painted_texts(&shapes).into_iter().filter(|(_, _, at)| lead.contains(at.center())).map(|(text, ..)| text).collect();
|
||||
assert_eq!(labels, ["Intensity"]);
|
||||
let labels: Vec<(String, bool)> =
|
||||
painted_texts(&shapes).into_iter().filter(|(_, _, at)| lead.contains(at.center())).map(|(text, cut, _)| (text, cut)).collect();
|
||||
assert_eq!(labels, [("Intensity".to_string(), false)], "labelled, and not cut short");
|
||||
let field = u.ctx.read_response(Id::new(("fx_gi", 0usize)).with("field")).expect("its value").rect;
|
||||
assert_eq!(field.max.x - lead.min.x, GLASS_FIELD_W, "the width the next test measures against");
|
||||
}
|
||||
|
||||
/// A glass settings field's width in the Design panel at its default width.
|
||||
const GLASS_FIELD_W: f32 = 98.0;
|
||||
const GLASS_FIELD_W: f32 = 98.5;
|
||||
|
||||
/// The glass settings' labels leave their values room in every language, and are cut only when
|
||||
/// they would crowd them (#256).
|
||||
/// The light intensity label this fix adds fits whole beside its value in every language (#256).
|
||||
/// Other glass labels may end in "…" in some languages (es "Profundidad"); a longer
|
||||
/// "Intensity" translation fails here.
|
||||
#[test]
|
||||
fn glass_labels_fit_beside_their_values_in_every_language() {
|
||||
fn the_intensity_label_fits_whole_in_every_language() {
|
||||
use crate::i18n::{self, Text};
|
||||
let keys = ["Light|glass", "Intensity", "Refraction", "Depth", "Dispersion", "Frost", "Splay"];
|
||||
let ctx = egui::Context::default();
|
||||
let mut out = ctx.run_ui(Default::default(), |ui| {
|
||||
let width = |s: &str| ui.painter().layout_no_wrap(s.to_string(), crate::theme::regular(11.0), egui::Color32::WHITE).size().x;
|
||||
for lang in i18n::languages() {
|
||||
for key in keys {
|
||||
let label = lang.ui.iter().find(|(k, _)| *k == key).map_or(key, |(_, t)| match t {
|
||||
Text::Plain(s) | Text::Plural { other: s, .. } => s,
|
||||
});
|
||||
let (lead, value) = (crate::widgets::text_lead_width(ui, label, GLASS_FIELD_W), width("100%"));
|
||||
assert!(lead + value <= GLASS_FIELD_W, "{}: no room for the value beside {label:?}", lang.code);
|
||||
// Cut off only when it would crowd the value's 32 points (es "Profundidad").
|
||||
if 12.0 + width(label) <= GLASS_FIELD_W - 32.0 {
|
||||
assert!(lead >= 12.0 + width(label), "{}: {label:?} is cut off", lang.code);
|
||||
}
|
||||
}
|
||||
let label = lang.ui.iter().find(|(k, _)| *k == "Intensity").map_or("Intensity", |(_, t)| match t {
|
||||
Text::Plain(s) | Text::Plural { other: s, .. } => s,
|
||||
});
|
||||
let lead = crate::widgets::text_lead_width(ui, label, GLASS_FIELD_W);
|
||||
assert!(lead >= 12.0 + width(label), "{}: {label:?} would end in \"…\"", lang.code);
|
||||
}
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
|
||||
@@ -223,7 +223,12 @@ fn number_field_impl(
|
||||
}
|
||||
match lead {
|
||||
Lead::Text(s) => {
|
||||
crate::bidi::paint_name(ui.painter(), pos2(lead_rect.min.x + 8.0, rect.center().y), s, regular(11.0), t.text_secondary, lead_w - 12.0);
|
||||
let galley = crate::bidi::name_galley(ui.painter(), s, regular(11.0), t.text_secondary, lead_w - 12.0);
|
||||
// A label cut short shows whole on hover.
|
||||
if galley.elided {
|
||||
lead_resp.clone().on_hover_text(s);
|
||||
}
|
||||
ui.painter().galley(pos2(lead_rect.min.x + 8.0, rect.center().y - galley.size().y / 2.0), galley, t.text_secondary);
|
||||
}
|
||||
Lead::Icon(i, _) => {
|
||||
icons::paint(ui.painter(), Rect::from_center_size(lead_rect.center() + vec2(1.0, 0.0), vec2(14.0, 14.0)), i, t.icon_secondary)
|
||||
@@ -347,7 +352,8 @@ fn number_field_impl(
|
||||
None => empty.to_string(),
|
||||
};
|
||||
let col = if value.is_some() { t.text } else { t.text_secondary };
|
||||
ui.painter().with_clip_rect(edit_rect).text(pos2(edit_rect.min.x, rect.center().y), Align2::LEFT_CENTER, s, regular(11.0), col);
|
||||
// A value too long for its room ends in "…", so a cut number never reads as another.
|
||||
crate::bidi::paint_name(ui.painter(), pos2(edit_rect.min.x, rect.center().y), &s, regular(11.0), col, edit_rect.width());
|
||||
}
|
||||
}
|
||||
// The variable button shows while the pointer is over a bindable field.
|
||||
|
||||
Reference in New Issue
Block a user