Justification: Auto Leading stores the shown percent, and the current choice is no edit

The Auto Leading field shows whole percents, and it now stores the
whole percent it shows, so a typed 500.4% (shown as 500%) is accepted
as 500% instead of being refused. Picking the Single Word
Justification the paragraphs already have is no longer an edit, so OK
adds no undo step for it.
This commit is contained in:
dotCooCoo committed 2026-11-11 20:06:28 -08:00
1 parent 27963d6d05
commit c69db89862
2 files changed
+34 -6

No files matched your search

+14 -2
View File
@@ -7716,6 +7716,12 @@ const JUSTIFY_ROWS: [(&str, &str, (f64, f64)); 3] = [
/// The allowed Auto Leading, in percent of the type size.
const AUTO_LEADING_RANGE: (f64, f64) = (0.0, 500.0);
/// The Auto Leading stored for a percent typed into its field: the whole percent the field shows.
fn auto_leading_typed(pct: f64) -> f64 {
// Adding 0.0 turns a rounded -0 into 0.
(pct.round() + 0.0) / 100.0
}
/// The Single Word Justification choices: (attribute value, label).
const SINGLE_WORD_CHOICES: [(&str, &str); 4] =
[("left", "Align Left"), ("center", "Align Center"), ("right", "Align Right"), ("fullyJustified", "Full Justify")];
@@ -7941,7 +7947,7 @@ fn justification(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, prefix: &str, cu
crate::rtl::label(ui, crate::i18n::tr(lang, "Auto Leading:"));
let auto = cur(d, "autoLeading").as_f64().map(|x| x * 100.0);
if let Some(n) = ui.scope(|ui| crate::widgets::number(ui, &format!("ps{prefix}autoLeading"), auto, "%", 60.0, 0)).inner {
d.fields.insert(format!("{prefix}autoLeading"), json!(n / 100.0));
d.fields.insert(format!("{prefix}autoLeading"), json!(auto_leading_typed(n)));
}
ui.end_row();
let single_label = crate::rtl::label(ui, crate::i18n::tr(lang, "Single Word Justification:"));
@@ -7954,7 +7960,13 @@ fn justification(lang: &str, ui: &mut egui::Ui, d: &mut Dialog, prefix: &str, cu
.show_ui(ui, |ui| {
for (v, label) in SINGLE_WORD_CHOICES {
if ui.selectable_label(single.as_str() == Some(v), crate::rtl::widget(ui, crate::i18n::tr(lang, label))).clicked() {
d.fields.insert(format!("{prefix}singleWordJustify"), json!(v));
// The paragraphs' own choice is no edit, so OK adds no undo step for it.
let key = format!("{prefix}singleWordJustify");
if current["singleWordJustify"].as_str() == Some(v) {
d.fields.remove(&key);
} else {
d.fields.insert(key, json!(v));
}
}
}
})
+20 -4
View File
@@ -1156,8 +1156,15 @@ fn justification_dialog_sets_auto_leading_and_single_word_justification() {
h.run_steps(3);
assert!(h.query_by_label("Auto Leading:").is_some());
assert!(h.query_by_label("Single Word Justification:").is_some());
// The dropdown shows the paragraph's Full Justify; pick Align Center.
h.get_by(|n| n.role() == egui::accesskit::Role::ComboBox && n.value().as_deref() == Some("Full Justify")).click();
use egui::accesskit::Role;
// The dropdown shows the paragraph's Full Justify. Picking Full Justify again is no edit.
h.get_by(|n| n.role() == Role::ComboBox && n.value().as_deref() == Some("Full Justify")).click();
h.run_steps(3);
h.get_by(|n| n.role() != Role::ComboBox && n.label().as_deref() == Some("Full Justify")).click();
h.run_steps(3);
assert!(!h.state().ui.dialog.as_ref().unwrap().fields.contains_key("singleWordJustify"), "the paragraph's own choice is no edit");
// Pick Align Center.
h.get_by(|n| n.role() == Role::ComboBox && n.value().as_deref() == Some("Full Justify")).click();
h.run_steps(3);
h.get_by_label("Align Center").click();
h.run_steps(3);
@@ -1170,8 +1177,8 @@ fn justification_dialog_sets_auto_leading_and_single_word_justification() {
let d = app.ui.dialog.clone().unwrap();
let before = undo_steps(&app);
let bad = [
("autoLeading", json!(5.004)),
("autoLeading", json!(-0.004)),
("autoLeading", json!(5.01)),
("autoLeading", json!(-0.01)),
("autoLeading", json!(f64::NAN)),
("singleWordJustify", json!("leftJustified")),
];
@@ -1183,6 +1190,15 @@ fn justification_dialog_sets_auto_leading_and_single_word_justification() {
}
assert_eq!(undo_steps(&app), before);
// A typed percent is stored as the whole percent the field shows, so 500.4% (shown as 500%)
// and -0.4% (shown as 0%) are accepted.
for (typed, stored) in [(500.4, 5.0), (-0.4, 0.0), (149.6, 1.5)] {
assert_eq!(auto_leading_typed(typed), stored, "{typed}%");
let mut probe = d.clone();
probe.fields.insert("autoLeading".into(), json!(auto_leading_typed(typed)));
assert_eq!(check_justification(&probe, "", &current), Ok(()), "{typed}%");
}
app.ui.dialog = Some(d);
app.ui.dialog.as_mut().unwrap().fields.insert("autoLeading".into(), json!(1.5));
draw(&mut app, &ctx);