/* Copyright 2024, Savanni D'Gerinel This file is part of FitnessTrax. FitnessTrax is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FitnessTrax is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FitnessTrax. If not, see . */ use crate::{components::TextEntry, types::ParseError}; use chrono::{Datelike, Local}; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; use std::{cell::RefCell, rc::Rc}; #[derive(Clone, Debug)] enum Part { Year, Month, Day, } pub struct DateFieldPrivate { value: Rc>, year: TextEntry, month: TextEntry, day: TextEntry, } #[glib::object_subclass] impl ObjectSubclass for DateFieldPrivate { const NAME: &'static str = "DateField"; type Type = DateField; type ParentType = gtk::Box; fn new() -> Self { let date = Local::now().date_naive(); let year = TextEntry::new( "year", Some(date.year()), |v| format!("{}", v), |v| v.parse::().map_err(|_| ParseError), |_| {}, ); let month = TextEntry::new( "month", Some(date.month()), |v| format!("{}", v), |v| v.parse::().map_err(|_| ParseError), |_| {}, ); let day = TextEntry::new( "day", Some(date.day()), |v| format!("{}", v), |v| v.parse::().map_err(|_| ParseError), |_| {}, ); Self { value: Rc::new(RefCell::new(date.clone())), year, month, day, } } } impl ObjectImpl for DateFieldPrivate {} impl WidgetImpl for DateFieldPrivate {} impl BoxImpl for DateFieldPrivate {} glib::wrapper! { pub struct DateField(ObjectSubclass) @extends gtk::Box, gtk::Widget; } /* Render a date in the format 2006 Jan 01. The entire date is editable. When the user moves to one part of the date, it will be erased and replaced with a grey placeholder. */ impl DateField { pub fn new(date: chrono::NaiveDate) -> Self { let s: Self = Object::builder().build(); println!("{}", date); s.append(&s.imp().year.widget()); s.append(&s.imp().month.widget()); s.append(&s.imp().day.widget()); s.imp().year.set_value(Some(date.year())); s.imp().month.set_value(Some(date.month())); s.imp().day.set_value(Some(date.day())); *s.imp().value.borrow_mut() = date; s } } /* As soon as the field gets focus, highlight the first element */ #[cfg(test)] mod test { use super::*; use crate::gtk_init::gtk_init; }