diff options
Diffstat (limited to 'src/app/form/repetition.rs')
-rw-r--r-- | src/app/form/repetition.rs | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/app/form/repetition.rs b/src/app/form/repetition.rs new file mode 100644 index 0000000..ac56479 --- /dev/null +++ b/src/app/form/repetition.rs @@ -0,0 +1,151 @@ +use gtk4 as gtk; + +use chrono::{Weekday, Weekday::*}; +use gtk::prelude::*; + +use crate::{ + model::event::Event, + model::{ + repetition, + repetition::{MonthFrequency, Repetition}, + }, +}; + +static WEEKDAYS_STR: [&str; 7] = [ + "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche", +]; + +static WEEKDAYS: [Weekday; 7] = [Mon, Tue, Wed, Thu, Fri, Sat, Sun]; + +pub struct Model { + pub view: gtk::Box, + pub no_radio: gtk::CheckButton, + pub day_interval_radio: gtk::CheckButton, + pub day_interval_entry: gtk::Entry, + pub monthly_radio: gtk::CheckButton, + pub monthly_entry: gtk::Entry, + pub first_day_radio: gtk::CheckButton, + pub first_day_dropdown: gtk::DropDown, + pub yearly_radio: gtk::CheckButton, +} + +pub fn view(event: &Event) -> Model { + let view = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .build(); + view.add_css_class("g-Form__Inputs"); + + view.append(&label("Répétition")); + + let no_radio = gtk::CheckButton::builder() + .label("Non") + .active(event.repetition.is_none()) + .build(); + view.append(&no_radio); + + let default = match event.repetition { + Some(Repetition::Daily { frequency }) => frequency.to_string(), + _ => "".to_string(), + }; + let day_interval_entry = gtk::Entry::builder().text(&default).build(); + let (day_interval_box, day_interval_radio) = radio_input( + &no_radio, + !default.is_empty(), + &day_interval_entry, + "Interval de jours", + ); + view.append(&day_interval_box); + + let default = match event.repetition { + Some(Repetition::Monthly { + frequency: MonthFrequency::Day { day }, + }) => day.to_string(), + _ => "".to_string(), + }; + let monthly_entry = gtk::Entry::builder().text(&default).build(); + let (monthly_box, monthly_radio) = + radio_input(&no_radio, !default.is_empty(), &monthly_entry, "Mensuel"); + view.append(&monthly_box); + + let (active, default) = match event.repetition { + Some(Repetition::Monthly { + frequency: MonthFrequency::FirstDay { day }, + }) => (true, day), + _ => (false, Mon), + }; + let first_day_dropdown = gtk::DropDown::from_strings(&WEEKDAYS_STR); + first_day_dropdown + .set_selected(WEEKDAYS.iter().position(|d| d == &default).unwrap_or(0) as u32); + let (first_day_of_month_box, first_day_radio) = + radio_input(&no_radio, active, &first_day_dropdown, "1er jour du mois"); + view.append(&first_day_of_month_box); + + let yearly_radio = gtk::CheckButton::builder() + .group(&no_radio) + .label("Annuel") + .active(event.repetition == Some(Repetition::Yearly)) + .build(); + view.append(&yearly_radio); + + Model { + view, + no_radio, + day_interval_radio, + day_interval_entry, + monthly_radio, + monthly_entry, + first_day_radio, + first_day_dropdown, + yearly_radio, + } +} + +fn radio_input( + radio_group: &impl IsA<gtk::CheckButton>, + active: bool, + input: &impl IsA<gtk::Widget>, + text: &str, +) -> (gtk::Box, gtk::CheckButton) { + let radio_box = gtk::Box::builder().build(); + let radio = gtk::CheckButton::builder() + .group(radio_group) + .label(text) + .active(active) + .build(); + radio_box.append(&radio); + input.add_css_class("g-Form__RadioInput"); + radio_box.append(input); + (radio_box, radio) +} + +fn label(text: &str) -> gtk::Label { + gtk::Label::builder() + .label(text) + .halign(gtk::Align::Start) + .margin_bottom(5) + .build() +} + +pub fn validate(model: &Model) -> Option<Repetition> { + if model.no_radio.is_active() { + None + } else if model.day_interval_radio.is_active() { + repetition::validate_day(&model.day_interval_entry.buffer().text()) + .map(|d| Repetition::Daily { frequency: d }) + } else if model.monthly_radio.is_active() { + repetition::validate_day(&model.monthly_entry.buffer().text()).map(|d| { + Repetition::Monthly { + frequency: MonthFrequency::Day { day: d }, + } + }) + } else if model.first_day_radio.is_active() { + let day = WEEKDAYS[model.first_day_dropdown.selected() as usize]; + Some(Repetition::Monthly { + frequency: MonthFrequency::FirstDay { day }, + }) + } else if model.yearly_radio.is_active() { + Some(Repetition::Yearly) + } else { + None + } +} |