From 3c5be0300f281d809cbe2ecdf52a4ef34598f084 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 21 Nov 2021 18:12:11 +0100 Subject: Show static events on the calendar --- src/main.rs | 171 +++++++++++++++++++++++++++++++++++++++++------------ src/model/event.rs | 39 ++++++++++++ src/model/mod.rs | 1 + src/style.css | 25 ++++++-- 4 files changed, 192 insertions(+), 44 deletions(-) create mode 100644 src/model/event.rs create mode 100644 src/model/mod.rs (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 072fbd5..557f8ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,30 +1,78 @@ -use chrono::{NaiveDate, Datelike, Weekday}; -use gtk4::gdk::Display; -use gtk4::prelude::*; -use gtk4::{ - Align, Application, ApplicationWindow, CssProvider, Grid, Label, Orientation, StyleContext, - STYLE_PROVIDER_PRIORITY_APPLICATION, Box as GtkBox -}; +mod model; + +use gtk4 as gtk; + +use chrono::{Datelike, NaiveDate, NaiveTime, Weekday}; +use gtk::gdk::Display; +use gtk::prelude::*; + +use crate::model::event::{Event, Time}; static DAYS: [&str; 7] = ["LUN", "MAR", "MER", "JEU", "VEN", "SAM", "DIM"]; -static MONTHES: [&str; 12] = ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Aoû", "Sep", "Oct", "Nov", "Déc"]; +static MONTHES: [&str; 12] = [ + "Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Aoû", "Sep", "Oct", "Nov", "Déc", +]; fn main() { - let application = Application::new(Some("me.guyonvarch.calendar"), Default::default()); - application.connect_startup(build_ui); + let mut events = [ + Event { + date: NaiveDate::from_ymd(2021, 11, 22), + time: Time::AllDay, + name: "Début de la semaine".to_string(), + }, + Event { + date: NaiveDate::from_ymd(2021, 11, 26), + time: Time::AllDay, + name: "Fin de la semaine".to_string(), + }, + Event { + date: NaiveDate::from_ymd(2021, 11, 26), + time: Time::Time { + start: NaiveTime::from_hms(15, 0, 0), + end: Some(NaiveTime::from_hms(15, 30, 0)), + }, + name: "Appel".to_string(), + }, + Event { + date: NaiveDate::from_ymd(2021, 11, 26), + time: Time::Time { + start: NaiveTime::from_hms(12, 0, 0), + end: Some(NaiveTime::from_hms(14, 0, 0)), + }, + name: "Repas".to_string(), + }, + Event { + date: NaiveDate::from_ymd(2021, 11, 26), + time: Time::Time { + start: NaiveTime::from_hms(8, 0, 0), + end: None, + }, + name: "Promener le chien".to_string(), + }, + Event { + date: NaiveDate::from_ymd(2021, 11, 26), + time: Time::Time { + start: NaiveTime::from_hms(9, 0, 0), + end: None, + }, + name: "Thé".to_string(), + }, + ] + .to_vec(); + events.sort_by_key(|e| e.time); + let application = gtk::Application::new(Some("me.guyonvarch.calendar"), Default::default()); + application.connect_startup(move |app| build_ui(app, &events)); application.run(); } -fn build_ui(application: &Application) { - let window = ApplicationWindow::new(application); +fn build_ui(app: >k::Application, events: &Vec) { + let window = gtk::ApplicationWindow::new(app); window.set_title(Some("Calendar")); window.set_default_size(800, 600); - window.set_hexpand(true); - window.set_vexpand(true); load_style(); - let grid = Grid::builder().build(); + let grid = gtk::Grid::builder().build(); window.set_child(Some(&grid)); @@ -38,7 +86,7 @@ fn build_ui(application: &Application) { let mut d = last_monday; for row in 1..5 { for col in 0..7 { - grid.attach(&day_entry(&today, &d), col, row, 1, 1); + grid.attach(&day_entry(&d, &today, &events), col, row, 1, 1); d = d.succ(); } } @@ -47,55 +95,100 @@ fn build_ui(application: &Application) { } fn load_style() { - let provider = CssProvider::new(); + let provider = gtk::CssProvider::new(); provider.load_from_data(include_bytes!("style.css")); - StyleContext::add_provider_for_display( + gtk::StyleContext::add_provider_for_display( &Display::default().expect("Error initializing gtk css provider."), &provider, - STYLE_PROVIDER_PRIORITY_APPLICATION, + gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, ); } -fn day_title(col: i32) -> GtkBox { - let vbox = GtkBox::builder() - .orientation(Orientation::Vertical) - .hexpand(true) +fn day_title(col: i32) -> gtk::Box { + let vbox = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) .build(); vbox.add_css_class("g-Calendar__DayTitle"); - let label = Label::builder() - .label(DAYS[col as usize]) - .halign(Align::Center) - .valign(Align::Center) - .build(); + let label = gtk::Label::builder().label(DAYS[col as usize]).build(); + vbox.append(&label); vbox } -fn day_entry(today: &NaiveDate, d: &NaiveDate) -> GtkBox { - let vbox = GtkBox::builder() - .orientation(Orientation::Vertical) - .hexpand(true) - .vexpand(true) +fn day_entry(date: &NaiveDate, today: &NaiveDate, events: &Vec) -> gtk::ScrolledWindow { + let vbox = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) .build(); vbox.add_css_class("g-Calendar__Day"); - if d == today { + if date == today { vbox.add_css_class("g-Calendar__Day--Today"); } - let label = Label::builder() - .label(&format!("{} {}", d.day(), MONTHES[d.month0() as usize])) - .halign(Align::Start) - .valign(Align::Center) + vbox.append(&day_label(date)); + + let events = events + .iter() + .filter(|e| e.date == *date) + .collect::>(); + + if !events.is_empty() { + vbox.append(&day_events(events)); + } + + let scrolled_window = gtk::ScrolledWindow::builder() + .hscrollbar_policy(gtk::PolicyType::Never) + .hexpand(true) + .vexpand(true) + .child(&vbox) + .build(); + + scrolled_window +} + +fn day_label(date: &NaiveDate) -> gtk::Label { + let label = gtk::Label::builder() + .label(&format!( + "{} {}", + date.day(), + MONTHES[date.month0() as usize] + )) + .halign(gtk::Align::Start) .build(); label.add_css_class("g-Calendar__DayNumber"); - vbox.append(&label); + label +} + +fn day_events(events: Vec<&Event>) -> gtk::Box { + let vbox = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .build(); + + for event in events { + let hbox = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .hexpand(true) + .build(); + + hbox.add_css_class("g-Calendar__DayEvent"); + + let event_txt = &event.pprint(); + let label = gtk::Label::builder() + .label(&event_txt) + .ellipsize(pango::EllipsizeMode::End) + .tooltip_text(&event_txt) + .halign(gtk::Align::Start) + .build(); + + hbox.append(&label); + vbox.append(&hbox); + } vbox } diff --git a/src/model/event.rs b/src/model/event.rs new file mode 100644 index 0000000..d1d9775 --- /dev/null +++ b/src/model/event.rs @@ -0,0 +1,39 @@ +use chrono::Timelike; +use chrono::{NaiveDate, NaiveTime}; + +#[derive(Debug, Clone)] +pub struct Event { + pub date: NaiveDate, + pub time: Time, + pub name: String, +} + +impl Event { + pub fn pprint(&self) -> String { + match self.time { + Time::AllDay => self.name.clone(), + Time::Time { start, end: None } => format!("{} {}", pprint_time(start), self.name), + Time::Time { + start, + end: Some(e), + } => format!("{}-{} {}", pprint_time(start), pprint_time(e), self.name), + } + } +} + +#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Eq, Ord)] +pub enum Time { + AllDay, + Time { + start: NaiveTime, + end: Option, + }, +} + +fn pprint_time(t: NaiveTime) -> String { + if t.minute() == 0 { + format!("{}h", t.hour()) + } else { + format!("{}h{}", t.hour(), t.minute()) + } +} diff --git a/src/model/mod.rs b/src/model/mod.rs new file mode 100644 index 0000000..53f1126 --- /dev/null +++ b/src/model/mod.rs @@ -0,0 +1 @@ +pub mod event; diff --git a/src/style.css b/src/style.css index bd58799..0a8292f 100644 --- a/src/style.css +++ b/src/style.css @@ -1,20 +1,35 @@ .g-Calendar__DayTitle { - border: 1px solid #CCCCCC; - font-weight: bold; + border-right: 1px solid #D2D2D2; + border-bottom: 1px solid #D2D2D2; padding: 4px; + background-color: white; + font-weight: bold; } .g-Calendar__Day { background-color: white; - border: 1px solid #CCCCCC; + border-right: 1px solid #D2D2D2; + border-bottom: 1px solid #D2D2D2; padding: 4px; } .g-Calendar__Day--Today { - background-color: #FFEC40; + background-color: #FFFCD8; } .g-Calendar__DayNumber { - color: #333333; font-size: 90%; + margin-bottom: 4px; +} + +.g-Calendar__DayEvent { + background-color: #A8C2E0; + color: white; + border-radius: 4px; + padding: 4px; + margin: 4px; +} + +.g-Calendar__DayEvent:hover { + background-color: pink; } -- cgit v1.2.3