mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Replace chrono with jiff (#8008)
`jiff` is more modern, and seem to be where the ecosystem is heading.
This commit is contained in:
@@ -34,7 +34,7 @@ default = ["dep:mime_guess2"]
|
||||
all_loaders = ["file", "http", "image", "svg", "gif", "webp"]
|
||||
|
||||
## Enable [`DatePickerButton`] widget.
|
||||
datepicker = ["chrono"]
|
||||
datepicker = ["jiff"]
|
||||
|
||||
## Add support for loading images from `file://` URIs.
|
||||
file = ["dep:mime_guess2"]
|
||||
@@ -83,7 +83,7 @@ profiling.workspace = true
|
||||
serde = { workspace = true, optional = true }
|
||||
|
||||
# Date operations needed for datepicker widget
|
||||
chrono = { workspace = true, optional = true, features = ["clock", "js-sys", "std", "wasmbind"] }
|
||||
jiff = { workspace = true, optional = true, features = ["std", "tz-system", "js"] }
|
||||
|
||||
## Enable this when generating docs.
|
||||
document-features = { workspace = true, optional = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::popup::DatePickerPopup;
|
||||
use chrono::NaiveDate;
|
||||
use egui::{Area, Button, Frame, InnerResponse, Key, Order, RichText, Ui, Widget};
|
||||
use jiff::civil::Date;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
@@ -11,7 +11,7 @@ pub(crate) struct DatePickerButtonState {
|
||||
|
||||
/// Shows a date, and will open a date picker popup when clicked.
|
||||
pub struct DatePickerButton<'a> {
|
||||
selection: &'a mut NaiveDate,
|
||||
selection: &'a mut Date,
|
||||
id_salt: Option<&'a str>,
|
||||
combo_boxes: bool,
|
||||
arrows: bool,
|
||||
@@ -20,13 +20,13 @@ pub struct DatePickerButton<'a> {
|
||||
show_icon: bool,
|
||||
format: String,
|
||||
highlight_weekends: bool,
|
||||
start_end_years: Option<RangeInclusive<i32>>,
|
||||
start_end_years: Option<RangeInclusive<i16>>,
|
||||
reverse_years: bool,
|
||||
year_scroll_to: Option<i32>,
|
||||
year_scroll_to: Option<i16>,
|
||||
}
|
||||
|
||||
impl<'a> DatePickerButton<'a> {
|
||||
pub fn new(selection: &'a mut NaiveDate) -> Self {
|
||||
pub fn new(selection: &'a mut Date) -> Self {
|
||||
Self {
|
||||
selection,
|
||||
id_salt: None,
|
||||
@@ -95,7 +95,7 @@ impl<'a> DatePickerButton<'a> {
|
||||
}
|
||||
|
||||
/// Change the format shown on the button. (Default: %Y-%m-%d)
|
||||
/// See [`chrono::format::strftime`] for valid formats.
|
||||
/// See [`jiff::fmt::strtime`] for valid formats.
|
||||
#[inline]
|
||||
pub fn format(mut self, format: impl Into<String>) -> Self {
|
||||
self.format = format.into();
|
||||
@@ -115,7 +115,7 @@ impl<'a> DatePickerButton<'a> {
|
||||
/// For example, if you want to provide the range of years from 2000 to 2035, you can use:
|
||||
/// `start_end_years(2000..=2035)`.
|
||||
#[inline]
|
||||
pub fn start_end_years(mut self, start_end_years: RangeInclusive<i32>) -> Self {
|
||||
pub fn start_end_years(mut self, start_end_years: RangeInclusive<i16>) -> Self {
|
||||
self.start_end_years = Some(start_end_years);
|
||||
self
|
||||
}
|
||||
@@ -130,7 +130,7 @@ impl<'a> DatePickerButton<'a> {
|
||||
/// Scroll the year dropdown to this year when the picker first opens.
|
||||
/// Defaults to the currently selected year.
|
||||
#[inline]
|
||||
pub fn year_scroll_to(mut self, year: i32) -> Self {
|
||||
pub fn year_scroll_to(mut self, year: i16) -> Self {
|
||||
self.year_scroll_to = Some(year);
|
||||
self
|
||||
}
|
||||
@@ -144,9 +144,9 @@ impl Widget for DatePickerButton<'_> {
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut text = if self.show_icon {
|
||||
RichText::new(format!("{} 📆", self.selection.format(&self.format)))
|
||||
RichText::new(format!("{} 📆", self.selection.strftime(&self.format)))
|
||||
} else {
|
||||
RichText::new(format!("{}", self.selection.format(&self.format)))
|
||||
RichText::new(format!("{}", self.selection.strftime(&self.format)))
|
||||
};
|
||||
let visuals = ui.visuals().widgets.open;
|
||||
if button_state.picker_visible {
|
||||
|
||||
@@ -4,32 +4,32 @@ mod button;
|
||||
mod popup;
|
||||
|
||||
pub use button::DatePickerButton;
|
||||
use chrono::{Datelike as _, Duration, NaiveDate, Weekday};
|
||||
use jiff::civil::{Date, ISOWeekDate, Weekday};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Week {
|
||||
number: u8,
|
||||
days: Vec<NaiveDate>,
|
||||
days: Vec<Date>,
|
||||
}
|
||||
|
||||
fn month_data(year: i32, month: u32) -> Vec<Week> {
|
||||
let first = NaiveDate::from_ymd_opt(year, month, 1).expect("Could not create NaiveDate");
|
||||
fn month_data(year: i16, month: i8) -> Vec<Week> {
|
||||
let first = Date::new(year, month, 1).expect("Could not create Date");
|
||||
let mut start = first;
|
||||
while start.weekday() != Weekday::Mon {
|
||||
start = start.checked_sub_signed(Duration::days(1)).unwrap();
|
||||
while start.weekday() != Weekday::Monday {
|
||||
start = start.yesterday().unwrap();
|
||||
}
|
||||
let mut weeks = vec![];
|
||||
let mut week = vec![];
|
||||
while start < first || start.month() == first.month() || start.weekday() != Weekday::Mon {
|
||||
while start < first || start.month() == first.month() || start.weekday() != Weekday::Monday {
|
||||
week.push(start);
|
||||
|
||||
if start.weekday() == Weekday::Sun {
|
||||
if start.weekday() == Weekday::Sunday {
|
||||
weeks.push(Week {
|
||||
number: start.iso_week().week() as u8,
|
||||
number: ISOWeekDate::from(start).week() as u8,
|
||||
days: std::mem::take(&mut week),
|
||||
});
|
||||
}
|
||||
start = start.checked_add_signed(Duration::days(1)).unwrap();
|
||||
start = start.tomorrow().unwrap();
|
||||
}
|
||||
|
||||
weeks
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use chrono::{Datelike as _, NaiveDate, Weekday};
|
||||
use jiff::civil::{Date, Weekday};
|
||||
|
||||
use egui::{Align, Button, Color32, ComboBox, Direction, Id, Layout, RichText, Ui, Vec2};
|
||||
|
||||
@@ -9,43 +9,39 @@ use crate::{Column, Size, StripBuilder, TableBuilder};
|
||||
#[derive(Default, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
struct DatePickerPopupState {
|
||||
year: i32,
|
||||
month: u32,
|
||||
day: u32,
|
||||
year: i16,
|
||||
month: i8,
|
||||
day: i8,
|
||||
setup: bool,
|
||||
year_scroll_needed: bool,
|
||||
}
|
||||
|
||||
impl DatePickerPopupState {
|
||||
fn last_day_of_month(&self) -> u32 {
|
||||
let date: NaiveDate =
|
||||
NaiveDate::from_ymd_opt(self.year, self.month, 1).expect("Could not create NaiveDate");
|
||||
date.with_day(31)
|
||||
.map(|_| 31)
|
||||
.or_else(|| date.with_day(30).map(|_| 30))
|
||||
.or_else(|| date.with_day(29).map(|_| 29))
|
||||
.unwrap_or(28)
|
||||
fn last_day_of_month(&self) -> i8 {
|
||||
Date::new(self.year, self.month, 1)
|
||||
.expect("Could not create Date")
|
||||
.days_in_month()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct DatePickerPopup<'a> {
|
||||
pub selection: &'a mut NaiveDate,
|
||||
pub selection: &'a mut Date,
|
||||
pub button_id: Id,
|
||||
pub combo_boxes: bool,
|
||||
pub arrows: bool,
|
||||
pub calendar: bool,
|
||||
pub calendar_week: bool,
|
||||
pub highlight_weekends: bool,
|
||||
pub start_end_years: Option<std::ops::RangeInclusive<i32>>,
|
||||
pub start_end_years: Option<std::ops::RangeInclusive<i16>>,
|
||||
pub reverse_years: bool,
|
||||
pub year_scroll_to: Option<i32>,
|
||||
pub year_scroll_to: Option<i16>,
|
||||
}
|
||||
|
||||
impl DatePickerPopup<'_> {
|
||||
/// Returns `true` if user pressed `Save` button.
|
||||
pub fn draw(&mut self, ui: &mut Ui) -> bool {
|
||||
let id = ui.make_persistent_id("date_picker");
|
||||
let today = chrono::offset::Utc::now().date_naive();
|
||||
let today = jiff::Zoned::now().date();
|
||||
let mut popup_state = ui
|
||||
.data_mut(|data| data.get_persisted::<DatePickerPopupState>(id))
|
||||
.unwrap_or_default();
|
||||
@@ -95,7 +91,7 @@ impl DatePickerPopup<'_> {
|
||||
};
|
||||
let scroll_to_year =
|
||||
self.year_scroll_to.unwrap_or(popup_state.year);
|
||||
let years: Vec<i32> = if self.reverse_years {
|
||||
let years: Vec<i16> = if self.reverse_years {
|
||||
(start_year..=end_year).rev().collect()
|
||||
} else {
|
||||
(start_year..=end_year).collect()
|
||||
@@ -132,7 +128,7 @@ impl DatePickerPopup<'_> {
|
||||
ComboBox::from_id_salt("date_picker_month")
|
||||
.selected_text(month_name(popup_state.month))
|
||||
.show_ui(ui, |ui| {
|
||||
for month in 1..=12 {
|
||||
for month in 1i8..=12 {
|
||||
if ui
|
||||
.selectable_value(
|
||||
&mut popup_state.month,
|
||||
@@ -156,7 +152,7 @@ impl DatePickerPopup<'_> {
|
||||
ComboBox::from_id_salt("date_picker_day")
|
||||
.selected_text(popup_state.day.to_string())
|
||||
.show_ui(ui, |ui| {
|
||||
for day in 1..=popup_state.last_day_of_month() {
|
||||
for day in 1i8..=popup_state.last_day_of_month() {
|
||||
if ui
|
||||
.selectable_value(
|
||||
&mut popup_state.day,
|
||||
@@ -333,9 +329,10 @@ impl DatePickerPopup<'_> {
|
||||
&& popup_state.day == day.day()
|
||||
{
|
||||
ui.visuals().selection.bg_fill
|
||||
} else if (day.weekday() == Weekday::Sat
|
||||
|| day.weekday() == Weekday::Sun)
|
||||
&& self.highlight_weekends
|
||||
} else if (matches!(
|
||||
day.weekday(),
|
||||
Weekday::Saturday | Weekday::Sunday
|
||||
)) && self.highlight_weekends
|
||||
{
|
||||
if ui.visuals().dark_mode {
|
||||
Color32::DARK_RED
|
||||
@@ -414,12 +411,12 @@ impl DatePickerPopup<'_> {
|
||||
strip.cell(|ui| {
|
||||
ui.with_layout(Layout::top_down_justified(Align::Center), |ui| {
|
||||
if ui.button("Save").clicked() {
|
||||
*self.selection = NaiveDate::from_ymd_opt(
|
||||
*self.selection = Date::new(
|
||||
popup_state.year,
|
||||
popup_state.month,
|
||||
popup_state.day,
|
||||
)
|
||||
.expect("Could not create NaiveDate");
|
||||
.expect("Could not create Date");
|
||||
saved = true;
|
||||
close = true;
|
||||
}
|
||||
@@ -442,7 +439,7 @@ impl DatePickerPopup<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn month_name(i: u32) -> &'static str {
|
||||
fn month_name(i: i8) -> &'static str {
|
||||
match i {
|
||||
1 => "January",
|
||||
2 => "February",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#![expect(clippy::manual_range_contains)]
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
#[cfg(feature = "datepicker")]
|
||||
mod datepicker;
|
||||
|
||||
pub mod syntax_highlighting;
|
||||
@@ -21,7 +21,7 @@ mod sizing;
|
||||
mod strip;
|
||||
mod table;
|
||||
|
||||
#[cfg(feature = "chrono")]
|
||||
#[cfg(feature = "datepicker")]
|
||||
pub use crate::datepicker::DatePickerButton;
|
||||
|
||||
pub(crate) use crate::layout::StripLayout;
|
||||
|
||||
Reference in New Issue
Block a user