mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-03 06:51:50 -06:00
M6: the date picker follows a whole date typed while it is open (#3393)
The calendar took its month once, when it opened, so a date typed while it was open showed only after leaving the field and coming back. It now moves to a date as soon as the text becomes one, and stays on the month it shows while the text is half typed or unchanged, so its arrows still turn the months.
This commit is contained in:
@@ -1420,6 +1420,7 @@ mod revert_draft_tests {
|
||||
press: None,
|
||||
calendar: None,
|
||||
calendar_rect: None,
|
||||
calendar_text: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ pub struct Focus {
|
||||
/// Date fields: the month the calendar shows (year, month 1–12), and where it was drawn.
|
||||
pub calendar: Option<(i32, u32)>,
|
||||
pub calendar_rect: Option<egui::Rect>,
|
||||
/// The text the calendar last saw, so it moves to a typed date once, when the typing becomes
|
||||
/// a whole date, and otherwise keeps the month its arrows turned to.
|
||||
pub calendar_text: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -90,6 +93,7 @@ fn open_focus(f: &FormField, widget: usize) -> Focus {
|
||||
press: None,
|
||||
calendar: None,
|
||||
calendar_rect: None,
|
||||
calendar_text: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,11 +259,19 @@ const MONTHS: [&str; 12] = ["January", "February", "March", "April", "May", "Jun
|
||||
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()?;
|
||||
let (mut y, mut m) = fx.calendar.unwrap_or_else(|| match parse_date(&fx.text, fmt) {
|
||||
Some(d) => (d.y, d.m),
|
||||
None => (today.0 as i32, today.1),
|
||||
});
|
||||
let current = parse_date(&fx.text, fmt);
|
||||
// A whole date typed since the last frame moves the calendar to it; half a date, or text
|
||||
// that hasn't changed, leaves it on the month it shows (the one the arrows turned to).
|
||||
let changed = fx.calendar_text.as_deref() != Some(fx.text.as_str());
|
||||
let (mut y, mut m) = match (fx.calendar, current) {
|
||||
(Some(_), Some(d)) if changed => (d.y, d.m),
|
||||
(Some(shown), _) => shown,
|
||||
(None, Some(d)) => (d.y, d.m),
|
||||
(None, None) => (today.0 as i32, today.1),
|
||||
};
|
||||
if changed {
|
||||
fx.calendar_text = Some(fx.text.clone());
|
||||
}
|
||||
let mut picked = None;
|
||||
let area = egui::Area::new(egui::Id::new(("date-picker", view.id.0)))
|
||||
.order(egui::Order::Foreground)
|
||||
|
||||
@@ -185,6 +185,39 @@ fn date_fields_offer_a_calendar() {
|
||||
assert_eq!(value(&h, "due"), vec![format!("{nm:02}/15/{ny}")], "picked in the field's format");
|
||||
}
|
||||
|
||||
/// The calendar used to keep the month it opened on, so a date typed while it was open showed
|
||||
/// only after leaving the field and coming back.
|
||||
#[test]
|
||||
fn the_calendar_follows_a_complete_date_typed_while_it_is_open() {
|
||||
use egui_kittest::kittest::Queryable;
|
||||
let mut h = harness();
|
||||
h.state_mut().apply_edit(pdfcraft_engine::Edit::AddField {
|
||||
page: 0,
|
||||
rect: [50.0, 40.0, 200.0, 60.0],
|
||||
kind: pdfcraft_engine::NewField::Date,
|
||||
name: Some("due".into()),
|
||||
});
|
||||
h.run_steps(4);
|
||||
click_field(&mut h, "due", 0);
|
||||
let (y, m, _) = h.state().session.today();
|
||||
let month =
|
||||
["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][(m - 1) as usize];
|
||||
h.get_by_label(&format!("{month} {y}"));
|
||||
// Half a date leaves the calendar where it is.
|
||||
h.event(egui::Event::Text("03/1".into()));
|
||||
h.run_steps(2);
|
||||
h.get_by_label(&format!("{month} {y}"));
|
||||
// The whole date moves it there.
|
||||
h.event(egui::Event::Text("4/2025".into()));
|
||||
h.run_steps(2);
|
||||
h.get_by_label("March 2025");
|
||||
// The arrows still turn the months, and the calendar stays on their month while the text
|
||||
// doesn't change.
|
||||
h.get_by_label("›").click();
|
||||
h.run_steps(3);
|
||||
h.get_by_label("April 2025");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lithuanian_calendar_localizes_months_and_weekdays_without_changing_field_values() {
|
||||
use egui_kittest::kittest::Queryable;
|
||||
|
||||
@@ -4620,8 +4620,8 @@ milestone = "M6"
|
||||
status = "shipped"
|
||||
commands = []
|
||||
tools = ["form_fill"]
|
||||
evidence = ["crates/ui-egui/tests/forms.rs::date_fields_offer_a_calendar"]
|
||||
notes = "a month calendar under date fields; the pick is written in the field's own date format"
|
||||
evidence = ["crates/ui-egui/tests/forms.rs::date_fields_offer_a_calendar", "crates/ui-egui/tests/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"
|
||||
|
||||
[[feature]]
|
||||
id = "form.auto-complete"
|
||||
|
||||
Reference in New Issue
Block a user