Merge PR #4343: M6: the date picker has a Today button (#4274)

This commit is contained in:
aiongg
2026-10-24 06:22:02 +00:00
36 changed files with 169 additions and 5 deletions
+21 -3
View File
@@ -290,8 +290,8 @@ pub(crate) fn commit(view: &mut DocView, form: &[FormField]) {
const MONTHS: [&str; 12] = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
/// The date picker under a focused date field. Returns the picked date, formatted with the
/// field's own format.
/// The date picker under a focused date field: a month of days, and a Today button under them.
/// Returns the picked date, formatted with the field's own format.
fn calendar(ctx: &egui::Context, view: &mut DocView, field: egui::Rect, fmt: &str, today: (i64, u32, u32)) -> Option<String> {
use pdfcraft_engine::form_scripts::{DateTime, format_date, parse_date};
let fx = view.forms.focus.as_mut()?;
@@ -345,7 +345,7 @@ fn calendar(ctx: &egui::Context, view: &mut DocView, field: egui::Rect, fmt: &st
(Some(a), Some(b)) => (b - a).num_days() as usize,
_ => 31,
};
egui::Grid::new(("date-grid", view.id.0)).spacing([4.0, 2.0]).show(ui, |ui| {
let grid = egui::Grid::new(("date-grid", view.id.0)).spacing([4.0, 2.0]).show(ui, |ui| {
for d in ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"] {
ui.label(egui::RichText::new(tl_ctx!("calendar weekday", d)).small());
}
@@ -381,6 +381,24 @@ fn calendar(ctx: &egui::Context, view: &mut DocView, field: egui::Rect, fmt: &st
}
}
});
// Today, whichever month the calendar shows: picked as a click on its day would
// pick it. A year the field's date can't hold offers no button.
if let Ok(ty) = i32::try_from(today.0) {
ui.add_space(4.0);
// As wide as the grid, so the button sits centred under it without widening the popup.
ui.allocate_ui_with_layout(vec2(grid.response.rect.width(), 0.0), egui::Layout::top_down(egui::Align::Center), |ui| {
let mut button = ui.small_button(tl!("Today"));
if let Some(month) = today.1.checked_sub(1).and_then(|i| MONTHS.get(i as usize)) {
button = button.on_hover_text(crate::i18n::fmt(
tl!("{month} {day}, {y}"),
&[("month", tl_ctx!("calendar date", month)), ("day", &today.2.to_string()), ("y", &ty.to_string())],
));
}
if button.clicked() {
picked = Some(format_date(DateTime { y: ty, m: today.1, d: today.2, hh: 0, mm: 0, ss: 0 }, fmt));
}
});
}
});
});
if let Some(fx) = view.forms.focus.as_mut() {
+3
View File
@@ -2791,3 +2791,6 @@ certificate Version الإصدار
field names can't contain a period: {name} لا يمكن أن تحتوي أسماء الحقول على نقطة: {name}
two cells would both be named {name} ستحمل خليتان الاسم نفسه {name}
a field named {name} already exists يوجد حقل باسم {name} بالفعل
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today اليوم
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2478,3 +2478,6 @@ animation effects Off Изключени
field names can't contain a period: {name} имената на полетата не може да съдържат точка: {name}
two cells would both be named {name} две клетки биха имали едно и също име {name}
a field named {name} already exists вече съществува поле с име {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Днес
Can't render this file because it contains an unexpected character in line 8 and column 16.
+3
View File
@@ -2774,3 +2774,6 @@ theme Appearance Aspecte
field names can't contain a period: {name} els noms dels camps no poden contenir cap punt: {name}
two cells would both be named {name} dues cel·les es dirien {name}
a field named {name} already exists ja existeix un camp anomenat {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Avui
Can't render this file because it contains an unexpected character in line 7 and column 3.
+3
View File
@@ -2713,3 +2713,6 @@ certificate Version وەشان
Make properties default کردنی تایبەتمەندییەکان بە بنەڕەتی
Pages selected پەڕە هەڵبژێردراوەکان
Page properties تایبەتمەندییەکانی پەڕە
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today ئەمڕۆ
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2822,3 +2822,6 @@ certificate Version Verze
field names can't contain a period: {name} názvy polí nesmějí obsahovat tečku: {name}
two cells would both be named {name} dvě buňky by se jmenovaly {name}
a field named {name} already exists pole s názvem {name} už existuje
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Dnes
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2516,3 +2516,6 @@ animation effects Off Aus
field names can't contain a period: {name} Feldnamen dürfen keinen Punkt enthalten: {name}
two cells would both be named {name} zwei Zellen hätten beide den Namen {name}
a field named {name} already exists ein Feld namens {name} ist bereits vorhanden
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Heute
Can't render this file because it contains an unexpected character in line 6 and column 51.
+3
View File
@@ -2521,3 +2521,6 @@ animation effects Off Ανενεργά
field names can't contain a period: {name} τα ονόματα πεδίων δεν μπορούν να περιέχουν τελεία: {name}
two cells would both be named {name} δύο κελιά θα είχαν το ίδιο όνομα {name}
a field named {name} already exists υπάρχει ήδη πεδίο με όνομα {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Σήμερα
Can't render this file because it contains an unexpected character in line 482 and column 9.
+3
View File
@@ -2838,3 +2838,6 @@ theme Appearance Aspecto
field names can't contain a period: {name} los nombres de campo no pueden contener un punto: {name}
two cells would both be named {name} dos celdas se llamarían {name}
a field named {name} already exists ya existe un campo llamado {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Hoy
Can't render this file because it contains an unexpected character in line 6 and column 60.
+3
View File
@@ -2783,3 +2783,6 @@ theme Appearance Teema
field names can't contain a period: {name} kenttien nimissä ei voi olla pistettä: {name}
two cells would both be named {name} kahdella solulla olisi sama nimi {name}
a field named {name} already exists kenttä nimeltä {name} on jo olemassa
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Tänään
Can't render this file because it contains an unexpected character in line 5 and column 47.
+3
View File
@@ -2781,3 +2781,6 @@ certificate Version Version
field names can't contain a period: {name} les noms de champ ne peuvent pas contenir de point : {name}
two cells would both be named {name} deux cellules porteraient le nom {name}
a field named {name} already exists un champ nommé {name} existe déjà
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Aujourd'hui
Can't render this file because it contains an unexpected character in line 6 and column 39.
+3
View File
@@ -2750,3 +2750,6 @@ theme Appearance स्वरूप
field names can't contain a period: {name} फ़ील्ड के नामों में पूर्ण विराम (.) नहीं हो सकता: {name}
two cells would both be named {name} दो सेल का नाम {name} हो जाएगा
a field named {name} already exists {name} नाम का फ़ील्ड पहले से मौजूद है
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today आज
Can't render this file because it contains an unexpected character in line 854 and column 12.
+3
View File
@@ -2514,3 +2514,6 @@ animation effects Off Ki
field names can't contain a period: {name} a mezőnevek nem tartalmazhatnak pontot: {name}
two cells would both be named {name} két cella neve is {name} lenne
a field named {name} already exists már van {name} nevű mező
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Ma
Can't render this file because it contains an unexpected character in line 7 and column 44.
+3
View File
@@ -2751,3 +2751,6 @@ theme Appearance Tampilan
field names can't contain a period: {name} nama kolom tidak boleh berisi titik: {name}
two cells would both be named {name} dua sel akan sama-sama bernama {name}
a field named {name} already exists kolom bernama {name} sudah ada
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Hari ini
Can't render this file because it contains an unexpected character in line 483 and column 12.
+3
View File
@@ -2747,3 +2747,6 @@ certificate SHA-256 digest Impronta SHA-256
field names can't contain a period: {name} i nomi dei campi non possono contenere un punto: {name}
two cells would both be named {name} due celle si chiamerebbero entrambe {name}
a field named {name} already exists esiste già un campo chiamato {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Oggi
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2515,3 +2515,6 @@ animation effects Off オフ
field names can't contain a period: {name} フィールド名にピリオドは使えません: {name}
two cells would both be named {name} 2 つのセルが同じ名前 {name} になります
a field named {name} already exists {name} という名前のフィールドは既にあります
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today 今日
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2513,3 +2513,6 @@ animation effects Off Өшірулі
field names can't contain a period: {name} өріс атауларында нүкте болмауы керек: {name}
two cells would both be named {name} екі ұяшықтың да атауы {name} болар еді
a field named {name} already exists {name} атты өріс бар
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Бүгін
Can't render this file because it contains an unexpected character in line 859 and column 9.
+3
View File
@@ -2750,3 +2750,6 @@ theme Appearance 모양
field names can't contain a period: {name} 필드 이름에는 마침표를 쓸 수 없습니다: {name}
two cells would both be named {name} 두 셀의 이름이 모두 {name}이(가) 됩니다
a field named {name} already exists {name}(이)라는 필드가 이미 있습니다
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today 오늘
Can't render this file because it contains an unexpected character in line 854 and column 12.
+3
View File
@@ -2429,3 +2429,6 @@ animation effects Off ປິດ
Make properties default ກຳນົດຄຸນສົມບັດເປັນຄ່າເລີ່ມຕົ້ນ
Pages selected ໜ້າທີ່ເລືອກ
Page properties ຄຸນສົມບັດໜ້າ
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today ມື້ນີ້
Can't render this file because it contains an unexpected character in line 6 and column 32.
+3
View File
@@ -2776,3 +2776,6 @@ theme Appearance Išvaizda
a table has 1 to {max} columns lentelėje gali būti nuo 1 iki {max} stulpelių
the first row number can be at most {max} pirmosios eilutės numeris gali būti ne didesnis nei {max}
the area, the spacing and the column widths must be numbers, the spacing 0 or more and each width more than 0 sritis, tarpai ir stulpelių pločiai turi būti skaičiai, tarpai – 0 arba daugiau, o kiekvienas plotis – daugiau nei 0
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Šiandien
Can't render this file because it contains an unexpected character in line 406 and column 9.
+3
View File
@@ -2694,3 +2694,6 @@ key Space Mellomrom
# Page gaps (AI-assisted, not separately native-reviewed)
Show gaps between pages Vis mellomrom mellom sidene
Hide gaps to join page edges. Margins inside the PDF remain unchanged. Skjul mellomrommene slik at sidekantene møtes. Margene inne i PDF-en endres ikke.
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today I dag
Can't render this file because it contains an unexpected character in line 8 and column 16.
+3
View File
@@ -2611,3 +2611,6 @@ animation effects Off Wyłączone
field names can't contain a period: {name} nazwy pól nie mogą zawierać kropki: {name}
two cells would both be named {name} dwie komórki miałyby nazwę {name}
a field named {name} already exists pole o nazwie {name} już istnieje
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Dzisiaj
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2800,3 +2800,6 @@ theme Appearance Aparência
a table has 1 to {max} columns uma tabela tem de 1 a {max} colunas
the first row number can be at most {max} o número da primeira linha pode ser no máximo {max}
the area, the spacing and the column widths must be numbers, the spacing 0 or more and each width more than 0 a área, o espaçamento e as larguras das colunas devem ser números, o espaçamento 0 ou mais e cada largura maior que 0
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Hoje
Can't render this file because it contains an unexpected character in line 9 and column 16.
+3
View File
@@ -2774,3 +2774,6 @@ theme Appearance Aspect
field names can't contain a period: {name} numele câmpurilor nu pot conține punct: {name}
two cells would both be named {name} două celule s-ar numi amândouă {name}
a field named {name} already exists există deja un câmp numit {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Astăzi
Can't render this file because it contains an unexpected character in line 3 and column 110.
+3
View File
@@ -2428,3 +2428,6 @@ animation effects Off Выкл
field names can't contain a period: {name} имена полей не могут содержать точку: {name}
two cells would both be named {name} две ячейки получили бы одно имя {name}
a field named {name} already exists поле с именем {name} уже существует
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Сегодня
Can't render this file because it contains an unexpected character in line 9 and column 16.
+3
View File
@@ -2520,3 +2520,6 @@ animation effects Off Izklopljeni
field names can't contain a period: {name} imena polj ne smejo vsebovati pike: {name}
two cells would both be named {name} dve celici bi imeli enako ime {name}
a field named {name} already exists polje z imenom {name} že obstaja
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Danes
Can't render this file because it contains an unexpected character in line 9 and column 16.
+3
View File
@@ -2500,3 +2500,6 @@ animation effects Off Joaktiv
field names can't contain a period: {name} emrat e fushave nuk mund të përmbajnë pikë: {name}
two cells would both be named {name} dy qeliza do të kishin të dyja emrin {name}
a field named {name} already exists ekziston tashmë një fushë me emrin {name}
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Sot
Can't render this file because it contains an unexpected character in line 9 and column 16.
+3
View File
@@ -2424,3 +2424,6 @@ animation effects Off ఆఫ్
field names can't contain a period: {name} ఫీల్డ్ పేర్లలో చుక్క ఉండకూడదు: {name}
two cells would both be named {name} రెండు గడులకూ {name} అనే పేరు వస్తుంది
a field named {name} already exists {name} అనే ఫీల్డ్ ఇప్పటికే ఉంది
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today ఈరోజు
Can't render this file because it contains an unexpected character in line 13 and column 16.
+3
View File
@@ -2681,3 +2681,6 @@ key Space Space
Page properties คุณสมบัติหน้า
The password must have at least 8 characters. รหัสผ่านต้องมีอย่างน้อย 8 ตัวอักษร
theme Appearance ลักษณะที่ปรากฏ
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today วันนี้
Can't render this file because it contains an unexpected character in line 865 and column 12.
+3
View File
@@ -2511,3 +2511,6 @@ animation effects Off Kapalı
field names can't contain a period: {name} alan adları nokta içeremez: {name}
two cells would both be named {name} iki hücrenin de adı {name} olurdu
a field named {name} already exists {name} adlı bir alan zaten var
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Bugün
Can't render this file because it contains an unexpected character in line 858 and column 9.
+3
View File
@@ -2537,3 +2537,6 @@ animation effects Off Вимкнено
field names can't contain a period: {name} імена полів не можуть містити крапку: {name}
two cells would both be named {name} дві клітинки мали б однакове ім'я {name}
a field named {name} already exists поле з іменем {name} уже існує
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Сьогодні
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -2780,3 +2780,6 @@ key Space Space
a table has 1 to {max} columns một bảng có từ 1 đến {max} cột
the first row number can be at most {max} số hàng đầu tiên tối đa là {max}
the area, the spacing and the column widths must be numbers, the spacing 0 or more and each width more than 0 vùng, khoảng cách và độ rộng cột phải là số, khoảng cách từ 0 trở lên và mỗi độ rộng lớn hơn 0
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today Hôm nay
Can't render this file because it contains an unexpected character in line 493 and column 12.
+3
View File
@@ -2479,3 +2479,6 @@ animation effects Off 关
field names can't contain a period: {name} 字段名称不能包含句点:{name}
two cells would both be named {name} 两个单元格的名称都会是 {name}
a field named {name} already exists 已存在名为 {name} 的字段
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today 今天
Can't render this file because it contains an unexpected character in line 9 and column 16.
+3
View File
@@ -2465,3 +2465,6 @@ animation effects Off 關
field names can't contain a period: {name} 欄位名稱不能包含句點:{name}
two cells would both be named {name} 兩個儲存格的名稱都會是 {name}
a field named {name} already exists 已有名為 {name} 的欄位
# Date picker: Today button (#4274) (AI-assisted, not separately native-reviewed)
Today 今天
Can't render this file because it contains an unexpected character in line 9 and column 16.
+47
View File
@@ -520,6 +520,53 @@ fn an_undelimited_date_field_takes_a_typed_date_and_its_calendar_opens_on_it() {
h.get_by_label("March 2025");
}
/// #4274: the calendar had no way to pick today; from another month the only way back was the
/// arrows. Today is picked in each field's own format, whichever month the calendar shows, and
/// is one edit as a clicked day is.
#[test]
fn the_calendar_picks_today_in_the_fields_format_from_any_month() {
use egui_kittest::kittest::Queryable;
let mut h = harness();
// 2023-11-14 on the injected clock.
let s = h.state_mut();
s.session = std::mem::take(&mut s.session).with_clock(|| 1_700_000_000);
assert_eq!(h.state().session.today(), (2023, 11, 14));
for (name, rect) in [("due", [50.0, 40.0, 200.0, 60.0]), ("start", [50.0, 80.0, 200.0, 100.0])] {
h.state_mut().apply_edit(pdfcraft_engine::Edit::AddField { page: 0, rect, kind: pdfcraft_engine::NewField::Date, name: Some(name.into()) });
}
assert!(h.state_mut().apply_edit(pdfcraft_engine::Edit::SetFieldProps {
name: "start".into(),
props: Box::new(pdfcraft_engine::FieldProps {
format: Some(pdfcraft_engine::form_scripts::Format::Date("yyyy-mm-dd".into())),
..Default::default()
}),
}));
h.run_steps(4);
// Two months on, and two months back: Today still picks the 14th of November.
for (name, arrow, shown, want) in [("due", "›", "January 2024", "11/14/2023"), ("start", "‹", "September 2023", "2023-11-14")] {
click_field(&mut h, name, 0);
h.get_by_label("November 2023");
for _ in 0..2 {
h.get_by_label(arrow).click();
h.run_steps(2);
}
h.get_by_label(shown);
if let Ok(dir) = std::env::var("PDFCRAFT_SHOTS") {
h.render().unwrap().save(format!("{dir}/calendar-today-{name}.png")).unwrap();
}
h.get_by_label("Today").click();
h.run_steps(4);
assert_eq!(value(&h, name), [want], "today in {name}'s format");
assert!(h.state().views[0].forms.focus.is_none(), "picking closes the field, as a clicked day does");
assert!(h.query_by_label("Today").is_none(), "and its calendar");
}
// One edit each, as a clicked day is.
h.state_mut().undo();
h.run_steps(2);
assert_eq!(value(&h, "start"), Vec::<String>::new());
assert_eq!(value(&h, "due"), ["11/14/2023"]);
}
#[test]
fn lithuanian_calendar_localizes_months_and_weekdays_without_changing_field_values() {
use egui_kittest::kittest::Queryable;
+2 -2
View File
@@ -4644,8 +4644,8 @@ milestone = "M6"
status = "shipped"
commands = []
tools = ["form_fill"]
evidence = ["crates/ui-egui/tests/it/forms.rs::date_fields_offer_a_calendar", "crates/ui-egui/tests/it/forms.rs::the_calendar_follows_a_complete_date_typed_while_it_is_open"]
notes = "a month calendar under date fields; the pick is written in the field's own date format; it opens on the field's date and moves to a whole date typed while it is open, staying on the month its arrows turned to otherwise"
evidence = ["crates/ui-egui/tests/it/forms.rs::date_fields_offer_a_calendar", "crates/ui-egui/tests/it/forms.rs::the_calendar_follows_a_complete_date_typed_while_it_is_open", "crates/ui-egui/tests/it/forms.rs::the_calendar_picks_today_in_the_fields_format_from_any_month"]
notes = "a month calendar under date fields; the pick is written in the field's own date format; it opens on the field's date and moves to a whole date typed while it is open, staying on the month its arrows turned to otherwise; a Today button under the days picks today from whichever month it shows, as a click on its day would (#4274)"
[[feature]]
id = "form.auto-complete"